Extend your language: Difference between revisions

Content added Content deleted
m (syntax highlighting fixup automation)
Line 32: Line 32:
Pick the syntax which suits your language. The keywords 'else1' and 'else2' are just examples. The new conditional expression should look, nest and behave analogously to the language's built-in 'if' statement.
Pick the syntax which suits your language. The keywords 'else1' and 'else2' are just examples. The new conditional expression should look, nest and behave analogously to the language's built-in 'if' statement.
=={{header|ABAP}}==
=={{header|ABAP}}==
<lang abap>DATA(result) = COND #( WHEN condition1istrue = abap_true AND condition2istrue = abap_true THEN bothconditionsaretrue
<syntaxhighlight lang="abap">DATA(result) = COND #( WHEN condition1istrue = abap_true AND condition2istrue = abap_true THEN bothconditionsaretrue
WHEN condition1istrue = abap_true THEN firstconditionistrue
WHEN condition1istrue = abap_true THEN firstconditionistrue
WHEN condition2istrue = abap_true THEN secondconditionistrue
WHEN condition2istrue = abap_true THEN secondconditionistrue
ELSE noconditionistrue ).
ELSE noconditionistrue ).
</syntaxhighlight>
</lang>
=={{header|6502 Assembly}}==
=={{header|6502 Assembly}}==
Although new opcodes cannot be created, they can be combined in ways to re-create opcodes on other architectures. Expanding the language is typically accomplished with macros or, if the hardware allows, self-modifying code.
Although new opcodes cannot be created, they can be combined in ways to re-create opcodes on other architectures. Expanding the language is typically accomplished with macros or, if the hardware allows, self-modifying code.
Line 42: Line 42:
This is an (admittedly messy) implementation of the double-conditional branch. Unfortunately due to the nature of the processor each branch type needs its own macro. For brevity's sake only <code>BEQ</code> will be displayed here. The rest can be created with simple copy-pasting and substitution.
This is an (admittedly messy) implementation of the double-conditional branch. Unfortunately due to the nature of the processor each branch type needs its own macro. For brevity's sake only <code>BEQ</code> will be displayed here. The rest can be created with simple copy-pasting and substitution.


<lang 6502asm>CMP_Double .macro ;NESASM3 syntax
<syntaxhighlight lang="6502asm">CMP_Double .macro ;NESASM3 syntax
; input:
; input:
; \1 = first condition. Valid addressing modes: immediate, zero page, or absolute.
; \1 = first condition. Valid addressing modes: immediate, zero page, or absolute.
Line 65: Line 65:
.doublefalse:
.doublefalse:
JMP \6 ;both are false
JMP \6 ;both are false
.endm</lang>
.endm</syntaxhighlight>


=={{header|68000 Assembly}}==
=={{header|68000 Assembly}}==
Line 72: Line 72:
I'm using VASM as my assembler, which does support macros, however, the use of macros is somewhat limited, as it's not easy to generalize to all data lengths, conditions, etc. A macro parameter can only take the place of an instruction argument, not an instruction itself. So I'd have to use separate macros for all the possible branch types. Thankfully, addressing modes can be generalized, so I don't have to write separate macros for each.
I'm using VASM as my assembler, which does support macros, however, the use of macros is somewhat limited, as it's not easy to generalize to all data lengths, conditions, etc. A macro parameter can only take the place of an instruction argument, not an instruction itself. So I'd have to use separate macros for all the possible branch types. Thankfully, addressing modes can be generalized, so I don't have to write separate macros for each.


<lang 68000devpac>macro if2_EQ_DOT_L 1,2,3,4
<syntaxhighlight lang="68000devpac">macro if2_EQ_DOT_L 1,2,3,4
;input: 1 = first param (can be any addressing mode compatible with CMP)
;input: 1 = first param (can be any addressing mode compatible with CMP)
; 2 = second param (used for condition 1)
; 2 = second param (used for condition 1)
Line 101: Line 101:
move.b #1,d0
move.b #1,d0
\@done:
\@done:
endm</lang>
endm</syntaxhighlight>
=={{header|Ada}}==
=={{header|Ada}}==


<lang Ada>with Ada.Text_IO; use Ada.Text_IO;
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;


procedure Test_If_2 is
procedure Test_If_2 is
Line 123: Line 123:
end case;
end case;
end loop;
end loop;
end Test_If_2;</lang>
end Test_If_2;</syntaxhighlight>


{{out}}
{{out}}
Line 143: Line 143:
Given agda's lack of a prelude, I have decided to define my own boolean type. That is however not necessary if you use, say, stdlib.
Given agda's lack of a prelude, I have decided to define my own boolean type. That is however not necessary if you use, say, stdlib.


<lang agda>
<syntaxhighlight lang="agda">


data Bool : Set where
data Bool : Set where
Line 161: Line 161:
example : Bool
example : Bool
example = if2 true , false then true else1 false else2 true else false
example = if2 true , false then true else1 false else2 true else false
</syntaxhighlight>
</lang>


=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
<lang algol68># operator to turn two boolean values into an integer - name inspired by the COBOL sample #
<syntaxhighlight lang="algol68"># operator to turn two boolean values into an integer - name inspired by the COBOL sample #
PRIO ALSO = 1;
PRIO ALSO = 1;
OP ALSO = ( BOOL a, b )INT: IF a AND b THEN 1 ELIF a THEN 2 ELIF b THEN 3 ELSE 4 FI;
OP ALSO = ( BOOL a, b )INT: IF a AND b THEN 1 ELIF a THEN 2 ELIF b THEN 3 ELSE 4 FI;
Line 176: Line 176:
, print( ( "second: only b is TRUE", newline ) )
, print( ( "second: only b is TRUE", newline ) )
, print( ( "neither: a and b are FALSE", newline ) )
, print( ( "neither: a and b are FALSE", newline ) )
ESAC</lang>
ESAC</syntaxhighlight>


=={{header|ALGOL W}}==
=={{header|ALGOL W}}==
In Algol W, a statement can be used as a parameter to a procedure that expects a procedure with no parameters (similarly, an expression can be passed for a parameterless procedure that returns the appropriate type).
In Algol W, a statement can be used as a parameter to a procedure that expects a procedure with no parameters (similarly, an expression can be passed for a parameterless procedure that returns the appropriate type).
<lang algolw>begin
<syntaxhighlight lang="algolw">begin
% executes pBoth, p1, p2 or pNeither %
% executes pBoth, p1, p2 or pNeither %
% depending on whether c1 and c2 are true, c1 is true, c2 is true %
% depending on whether c1 and c2 are true, c1 is true, c2 is true %
Line 203: Line 203:
)
)
end
end
end.</lang>
end.</syntaxhighlight>


=={{header|Arturo}}==
=={{header|Arturo}}==
<lang rebol>if2: function [cond1 cond2 both one two none][
<syntaxhighlight lang="rebol">if2: function [cond1 cond2 both one two none][
case []
case []
when? [and? cond1 cond2] -> do both
when? [and? cond1 cond2] -> do both
Line 217: Line 217:
[print "only first"]
[print "only first"]
[print "only second"]
[print "only second"]
[print "none"]</lang>
[print "none"]</syntaxhighlight>
{{out}}
{{out}}
Line 227: Line 227:
See also [[#OCaml|OCaml]] and [[#Standard_ML|Standard ML]].
See also [[#OCaml|OCaml]] and [[#Standard_ML|Standard ML]].


<lang ATS>(* Languages with pattern matching ALREADY HAVE THIS! *)
<syntaxhighlight lang="ats">(* Languages with pattern matching ALREADY HAVE THIS! *)


fn
fn
Line 244: Line 244:
func (false, true);
func (false, true);
func (false, false)
func (false, false)
end</lang>
end</syntaxhighlight>
{{out}}
{{out}}
<pre>$ patscc extend_your_language.dats && ./a.out
<pre>$ patscc extend_your_language.dats && ./a.out
Line 255: Line 255:
This task requires syntax different from the <code>if</code> keyword in C. For example:
This task requires syntax different from the <code>if</code> keyword in C. For example:


<lang c>/* Four-way branch.
<syntaxhighlight lang="c">/* Four-way branch.
*
*
* if2 (firsttest, secondtest
* if2 (firsttest, secondtest
Line 271: Line 271:
case 3: bothfalse; break;\
case 3: bothfalse; break;\
}
}
</syntaxhighlight>
</lang>


Example application:
Example application:


<lang c>#include <limits.h>
<syntaxhighlight lang="c">#include <limits.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
Line 298: Line 298:
}
}
return 0;
return 0;
}</lang>
}</syntaxhighlight>


Example invocation:
Example invocation:


<lang bash>$ make exten && ./exten 3 33 333 3a b " " -2
<syntaxhighlight lang="bash">$ make exten && ./exten 3 33 333 3a b " " -2
cc exten.c -o exten
cc exten.c -o exten
3: a number
3: a number
Line 310: Line 310:
b: not a number
b: not a number
: not a number
: not a number
-2: a number</lang>
-2: a number</syntaxhighlight>


The following is probably easier to read, although <code>fi2</code> is funny looking however you slice it. On the other hand, this kind of macros are unquestionably in the "bad" category.
The following is probably easier to read, although <code>fi2</code> is funny looking however you slice it. On the other hand, this kind of macros are unquestionably in the "bad" category.
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>


#define if2(a, b) switch(((a)) + ((b)) * 2) { case 3:
#define if2(a, b) switch(((a)) + ((b)) * 2) { case 3:
Line 346: Line 346:


return 0;
return 0;
}</lang>
}</syntaxhighlight>


=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==
<lang csharp>
<syntaxhighlight lang="csharp">


using System;
using System;
Line 478: Line 478:
}
}


</syntaxhighlight>
</lang>
{{out| Program Output}}
{{out| Program Output}}
<pre>
<pre>
Line 497: Line 497:
=={{header|Clay}}==
=={{header|Clay}}==


<lang clay>alias if2(cond1:Bool,
<syntaxhighlight lang="clay">alias if2(cond1:Bool,
cond2:Bool,
cond2:Bool,
both,
both,
Line 512: Line 512:
return neither;
return neither;
}
}
</syntaxhighlight>
</lang>


=={{header|Clojure}}==
=={{header|Clojure}}==
Clojure being a LISP has macros.
Clojure being a LISP has macros.


<lang clojure>
<syntaxhighlight lang="clojure">
(defmacro if2 [[cond1 cond2] bothTrue firstTrue secondTrue else]
(defmacro if2 [[cond1 cond2] bothTrue firstTrue secondTrue else]
`(let [cond1# ~cond1
`(let [cond1# ~cond1
Line 523: Line 523:
(if cond1# (if cond2# ~bothTrue ~firstTrue)
(if cond1# (if cond2# ~bothTrue ~firstTrue)
(if cond2# ~secondTrue ~else))))
(if cond2# ~secondTrue ~else))))
</syntaxhighlight>
</lang>


<pre>
<pre>
Line 541: Line 541:


An alternative, cleaner way using case macro of Clojure:
An alternative, cleaner way using case macro of Clojure:
<lang clojure>
<syntaxhighlight lang="clojure">
(defmacro if2
(defmacro if2
[cond1 cond2 both-true first-true second-true both-false]
[cond1 cond2 both-true first-true second-true both-false]
Line 549: Line 549:
[false true] ~second-true
[false true] ~second-true
[false false] ~both-false))
[false false] ~both-false))
</syntaxhighlight>
</lang>


<pre>
<pre>
Line 560: Line 560:
=={{header|COBOL}}==
=={{header|COBOL}}==
Cobol already has a multiple-if:
Cobol already has a multiple-if:
<lang cobol>
<syntaxhighlight lang="cobol">
EVALUATE EXPRESSION-1 ALSO EXPRESSION-2
EVALUATE EXPRESSION-1 ALSO EXPRESSION-2
WHEN TRUE ALSO TRUE
WHEN TRUE ALSO TRUE
Line 571: Line 571:
DISPLAY 'Neither is true.'
DISPLAY 'Neither is true.'
END-EVALUATE
END-EVALUATE
</syntaxhighlight>
</lang>
(Of course, Cobol is also inherently non-extensible.)
(Of course, Cobol is also inherently non-extensible.)


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==


<lang lisp>(defmacro if2 (cond1 cond2 both first second &rest neither)
<syntaxhighlight lang="lisp">(defmacro if2 (cond1 cond2 both first second &rest neither)
(let ((res1 (gensym))
(let ((res1 (gensym))
(res2 (gensym)))
(res2 (gensym)))
Line 584: Line 584:
(,res1 ,first)
(,res1 ,first)
(,res2 ,second)
(,res2 ,second)
(t ,@neither)))))</lang>
(t ,@neither)))))</syntaxhighlight>


Interactive tests to validate if2.
Interactive tests to validate if2.
Line 638: Line 638:
=={{header|Coq}}==
=={{header|Coq}}==
Coq allows "[https://coq.inria.fr/refman/user-extensions/syntax-extensions.html syntax extensions]":
Coq allows "[https://coq.inria.fr/refman/user-extensions/syntax-extensions.html syntax extensions]":
<lang coq>
<syntaxhighlight lang="coq">
Notation "A /\ B" := (and A B)
Notation "A /\ B" := (and A B)
</syntaxhighlight>
</lang>


=={{header|D}}==
=={{header|D}}==
D features lazy arguments, which can be used for this task.
D features lazy arguments, which can be used for this task.


<lang d>void if2(T1, T2, T3, T4)(in bool c1, in bool c2,
<syntaxhighlight lang="d">void if2(T1, T2, T3, T4)(in bool c1, in bool c2,
lazy T1 first,
lazy T1 first,
lazy T2 both,
lazy T2 both,
Line 676: Line 676:
test(3 > 4, 3 > 4);
test(3 > 4, 3 > 4);
test(3 > 4, 1 < 2);
test(3 > 4, 1 < 2);
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>first
<pre>first
Line 687: Line 687:
First example:
First example:


<lang delphi>
<syntaxhighlight lang="delphi">
procedure Check(Condition1: Boolean; Condition2: Boolean)
procedure Check(Condition1: Boolean; Condition2: Boolean)
begin
begin
Line 702: Line 702:
else
else
NoConditionIsTrue;
NoConditionIsTrue;
end;</lang>
end;</syntaxhighlight>


Second example:
Second example:


<lang delphi>
<syntaxhighlight lang="delphi">
procedure Check(Condition1: Boolean; Condition2: Boolean)
procedure Check(Condition1: Boolean; Condition2: Boolean)
begin
begin
Line 716: Line 716:
SecondConditionIsTrue
SecondConditionIsTrue
else NoConditionIsTrue;
else NoConditionIsTrue;
end;</lang>
end;</syntaxhighlight>


In both examples if Condition1 and/or Condition2 are Booleans you can omit the '= True' (not when for instance comparing Integers: a = 1)
In both examples if Condition1 and/or Condition2 are Booleans you can omit the '= True' (not when for instance comparing Integers: a = 1)
Line 740: Line 740:
Execution of the proper lambda can be realized by manipulating the return stack with <code>(</code> (move from data stack to return stack) <code>)</code> (move from return stack to data stack) in two nested if-blocks. Usually the start locations of lambdas and locations of operators like <code>?</code> are stored on the return stack.
Execution of the proper lambda can be realized by manipulating the return stack with <code>(</code> (move from data stack to return stack) <code>)</code> (move from return stack to data stack) in two nested if-blocks. Usually the start locations of lambdas and locations of operators like <code>?</code> are stored on the return stack.


<lang dup>{two-conditional if operator implementation}
<syntaxhighlight lang="dup">{two-conditional if operator implementation}
{ [ top cond. = true ][ top cond. = false ]}
{ [ top cond. = true ][ top cond. = false ]}
{ [ 2nd = true ][2nd = false ] [ 2nd = true ][ 2nd = false] }
{ [ 2nd = true ][2nd = false ] [ 2nd = true ][ 2nd = false] }
[(((([[)))!)))%%%%%][)))))!)%%%%%]?][[))))!))%%%%%][))))))!%%%%%]?]?]⇒¿
[(((([[)))!)))%%%%%][)))))!)%%%%%]?][[))))!))%%%%%][))))))!%%%%%]?]?]⇒¿
</syntaxhighlight>
</lang>


Example program:
Example program:


<lang dup>0 1_['t,'t,]['t,'f,]['f,'t,]['f,'f,]¿</lang>
<syntaxhighlight lang="dup">0 1_['t,'t,]['t,'f,]['f,'t,]['f,'f,]¿</syntaxhighlight>


Resulting output of the example program:
Resulting output of the example program:
Line 762: Line 762:
The control structure is built up and then executed by chained method calls (similar to jQuery) starting from the <var>controlName</var> object, one for each {}, each of which takes a closure as a parameter. The first closure actually returns the parenthesized <var>args</var> evaluated and a closure for the first {}, which the args are in scope for; the closures for all following {} do not have the <var>args</var> in scope.
The control structure is built up and then executed by chained method calls (similar to jQuery) starting from the <var>controlName</var> object, one for each {}, each of which takes a closure as a parameter. The first closure actually returns the parenthesized <var>args</var> evaluated and a closure for the first {}, which the args are in scope for; the closures for all following {} do not have the <var>args</var> in scope.


<lang e>pragma.enable("lambda-args") # The feature is still experimental syntax
<syntaxhighlight lang="e">pragma.enable("lambda-args") # The feature is still experimental syntax


def makeIf2Control(evalFn, tf, ft, ff) {
def makeIf2Control(evalFn, tf, ft, ff) {
Line 805: Line 805:
}
}
}
}
}</lang>
}</syntaxhighlight>


The internal expansion of the "if2" block above is:
The internal expansion of the "if2" block above is:


<lang e>if2.then__control_2_0(fn {
<syntaxhighlight lang="e">if2.then__control_2_0(fn {
[[a, b], fn {
[[a, b], fn {
println("both")
println("both")
Line 819: Line 819:
}).else__control_0(fn {
}).else__control_0(fn {
println("neither")
println("neither")
}).run__control()</lang>
}).run__control()</syntaxhighlight>


=={{header|EchoLisp}}==
=={{header|EchoLisp}}==
'''define-syntax''' and '''define-syntax-rules''' are here to extend the language
'''define-syntax''' and '''define-syntax-rules''' are here to extend the language
<lang scheme>
<syntaxhighlight lang="scheme">
(define-syntax-rule
(define-syntax-rule
(if2 cond1 cond2 both cond1-only cond2-only none) ;; new syntax
(if2 cond1 cond2 both cond1-only cond2-only none) ;; new syntax
Line 848: Line 848:
→ "positive and inexact"
→ "positive and inexact"


</syntaxhighlight>
</lang>


=={{header|Emacs Lisp}}==
=={{header|Emacs Lisp}}==
The same macro that works in Common Lisp will work in Emacs Lisp for this problem:
The same macro that works in Common Lisp will work in Emacs Lisp for this problem:
<lang lisp>
<syntaxhighlight lang="lisp">
(defmacro if2 (cond1 cond2 both first second &rest neither)
(defmacro if2 (cond1 cond2 both first second &rest neither)
(let ((res1 (gensym))
(let ((res1 (gensym))
Line 862: Line 862:
(,res2 ,second)
(,res2 ,second)
(t ,@neither)))))
(t ,@neither)))))
</syntaxhighlight>
</lang>
{{Out}}
{{Out}}
Interactive tests to validate if2.
Interactive tests to validate if2.
Line 897: Line 897:


=={{header|F_Sharp|F#}}==
=={{header|F_Sharp|F#}}==
<lang fsharp>
<syntaxhighlight lang="fsharp">
// Extend your language. Nigel Galloway: September 14th., 2021
// Extend your language. Nigel Galloway: September 14th., 2021
type elsetf=TF
type elsetf=TF
Line 920: Line 920:
elseft (fun()->printfn "ft")
elseft (fun()->printfn "ft")
elseff (fun()->printfn "ff")
elseff (fun()->printfn "ff")
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 929: Line 929:
</pre>
</pre>
Looking at some possible errors found by the compiler:
Looking at some possible errors found by the compiler:
<lang fsharp>
<syntaxhighlight lang="fsharp">
if2 (13<23) (23<42) (fun()->printfn "tt")
if2 (13<23) (23<42) (fun()->printfn "tt")
elseff (fun()->printfn "tf")
elseff (fun()->printfn "tf")
elseft (fun()->printfn "ft")
elseft (fun()->printfn "ft")
elseff (fun()->printfn "ff")
elseff (fun()->printfn "ff")
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 942: Line 942:
'elseff'
'elseff'
</pre>
</pre>
<lang fsharp>
<syntaxhighlight lang="fsharp">
if2 (13<23) (42<23) (fun()->printfn "tt")
if2 (13<23) (42<23) (fun()->printfn "tt")
elsetx (fun()->printfn "tf")
elsetx (fun()->printfn "tf")
elseft (fun()->printfn "ft")
elseft (fun()->printfn "ft")
elseff (fun()->printfn "ff")
elseff (fun()->printfn "ff")
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 957: Line 957:
=={{header|Factor}}==
=={{header|Factor}}==
Not too hard, as long as you're not worried about choking to death on stack effects:
Not too hard, as long as you're not worried about choking to death on stack effects:
<lang factor>( scratchpad ) : 2ifte ( ..a ?0 ?1 quot0: ( ..a -- ..b ) quot1: ( ..a -- ..b ) quot2: ( ..a -- ..b ) quot3: ( ..a -- ..b ) -- ..b )
<syntaxhighlight lang="factor">( scratchpad ) : 2ifte ( ..a ?0 ?1 quot0: ( ..a -- ..b ) quot1: ( ..a -- ..b ) quot2: ( ..a -- ..b ) quot3: ( ..a -- ..b ) -- ..b )
[ [ if ] curry curry ] 2bi@ if ; inline
[ [ if ] curry curry ] 2bi@ if ; inline
( scratchpad ) 3 [ 0 > ] [ even? ] bi [ 0 ] [ 1 ] [ 2 ] [ 3 ] 2ifte .
( scratchpad ) 3 [ 0 > ] [ even? ] bi [ 0 ] [ 1 ] [ 2 ] [ 3 ] 2ifte .
2</lang>
2</syntaxhighlight>


=={{header|Fennel}}==
=={{header|Fennel}}==
<lang fennel>;; Fennel, being a Lisp, provides a way to define macros for new syntax.
<syntaxhighlight lang="fennel">;; Fennel, being a Lisp, provides a way to define macros for new syntax.
;; The "`" and "," characters are used to construct a template for the macro.
;; The "`" and "," characters are used to construct a template for the macro.
(macro if2 [cond1 cond2 both first second none]
(macro if2 [cond1 cond2 both first second none]
Line 980: Line 980:
(test-if2 true false) ;"first"
(test-if2 true false) ;"first"
(test-if2 false true) ;"second"
(test-if2 false true) ;"second"
(test-if2 false false) ;"none"</lang>
(test-if2 false false) ;"none"</syntaxhighlight>


=={{header|Forth}}==
=={{header|Forth}}==
Control structures in Forth are just IMMEDIATE words, which flags them to be run at compile time. POSTPONE invokes the compile-time semantics of words instead of executing them.
Control structures in Forth are just IMMEDIATE words, which flags them to be run at compile time. POSTPONE invokes the compile-time semantics of words instead of executing them.
<lang forth>\ in this construct, either of the ELSE clauses may be omitted, just like IF-THEN.
<syntaxhighlight lang="forth">\ in this construct, either of the ELSE clauses may be omitted, just like IF-THEN.


: BOTH postpone IF postpone IF ; immediate
: BOTH postpone IF postpone IF ; immediate
Line 998: Line 998:
NEITHER drop ;
NEITHER drop ;
: fizzbuzz ( n -- ) 0 do i 1+ fb loop ;
: fizzbuzz ( n -- ) 0 do i 1+ fb loop ;
</syntaxhighlight>
</lang>


=={{header|Fortran}}==
=={{header|Fortran}}==
Fortran does not offer language extension facilities except in the form of allowing a programmer to define subroutines and especially functions, that extend the collection of library functions and which could look a bit like a new statement form if viewed sympathetically. Similarly, there is no built-in pre-processor (as in pl/i) which would enable the definition of what could look like an additional statement form. So, you're stuck with something like <code>call DIRECTWRITE(F,FMT,B,X + 7)</code> in place of <code>WRITE (F,FMT) B,X + 7</code> where one is to pass over the appearance of "call" and disregard the placement of the ")" symbol.
Fortran does not offer language extension facilities except in the form of allowing a programmer to define subroutines and especially functions, that extend the collection of library functions and which could look a bit like a new statement form if viewed sympathetically. Similarly, there is no built-in pre-processor (as in pl/i) which would enable the definition of what could look like an additional statement form. So, you're stuck with something like <code>call DIRECTWRITE(F,FMT,B,X + 7)</code> in place of <code>WRITE (F,FMT) B,X + 7</code> where one is to pass over the appearance of "call" and disregard the placement of the ")" symbol.


Even so, Fortran programmers often confront a need for multiple condition tests, and, there being no [[Decision_tables|"decision table"]] construction, one might proceed as follows: <lang Fortran> LOGICAL A,B !These are allocated the same storage
Even so, Fortran programmers often confront a need for multiple condition tests, and, there being no [[Decision_tables|"decision table"]] construction, one might proceed as follows: <syntaxhighlight lang="fortran"> LOGICAL A,B !These are allocated the same storage
INTEGER IA,IB !As the default integer size.
INTEGER IA,IB !As the default integer size.
EQUIVALENCE (IA,A),(IB,B) !So, this will cause no overlaps.
EQUIVALENCE (IA,A),(IB,B) !So, this will cause no overlaps.
Line 1,053: Line 1,053:


999 CONTINUE
999 CONTINUE
END</lang>
END</syntaxhighlight>
Which is to say that prior to Fortran 66 there were no LOGICAL variables, so one employed integer variables and used integer arithmetic with + and * for .OR. and .AND. on variables with the obvious values of zero and one - though additional values may be considered for more complex state collections with more complex calculations in mind. This involves re-interpreting what might appear to be integer arithmetic, but is not much of an extension to the language. With the introduction of LOGICAL variables and their associated operators, the results could be unexpected, as shown in the third lot of output:
Which is to say that prior to Fortran 66 there were no LOGICAL variables, so one employed integer variables and used integer arithmetic with + and * for .OR. and .AND. on variables with the obvious values of zero and one - though additional values may be considered for more complex state collections with more complex calculations in mind. This involves re-interpreting what might appear to be integer arithmetic, but is not much of an extension to the language. With the introduction of LOGICAL variables and their associated operators, the results could be unexpected, as shown in the third lot of output:
<pre>
<pre>
Line 1,074: Line 1,074:
TT -1 -1 -3
TT -1 -1 -3
</pre>
</pre>
Different compilers/systems may use different values for ''true'' and ''false'' and indeed on the IBM360 ''et seq'', Fortran and pl/i did just that. Nevertheless, it would be easy enough to extend the language by adding a function such as: <lang Fortran> INTEGER FUNCTION IF2(A,B) !Combine two LOGICAL variables.
Different compilers/systems may use different values for ''true'' and ''false'' and indeed on the IBM360 ''et seq'', Fortran and pl/i did just that. Nevertheless, it would be easy enough to extend the language by adding a function such as: <syntaxhighlight lang="fortran"> INTEGER FUNCTION IF2(A,B) !Combine two LOGICAL variables.
LOGICAL A,B !These.
LOGICAL A,B !These.
IF2 = 0 !Wasted effort if A is true.
IF2 = 0 !Wasted effort if A is true.
IF (A) IF2 = 2 !But it avoids IF ... THEN ... ELSE ... END IF blather.
IF (A) IF2 = 2 !But it avoids IF ... THEN ... ELSE ... END IF blather.
IF (B) IF2 = IF2 + 1 !This relies on IF2 being a variable. (Standard in F90+)
IF (B) IF2 = IF2 + 1 !This relies on IF2 being a variable. (Standard in F90+)
END FUNCTION IF2 !Thus produce a four-way result.</lang>
END FUNCTION IF2 !Thus produce a four-way result.</syntaxhighlight>
which ignores the possibly peculiar numerical values of LOGICAL variables. The results of such a function could then be employed in a computed GO TO statement as above, or, in the SELECT CASE statement that is preferred by more modern programmers: <lang Fortran> SELECT CASE(IF2(A,B))
which ignores the possibly peculiar numerical values of LOGICAL variables. The results of such a function could then be employed in a computed GO TO statement as above, or, in the SELECT CASE statement that is preferred by more modern programmers: <syntaxhighlight lang="fortran"> SELECT CASE(IF2(A,B))
CASE(B"00"); WRITE (6,*) "Both false."
CASE(B"00"); WRITE (6,*) "Both false."
CASE(B"01"); WRITE (6,*) "B only."
CASE(B"01"); WRITE (6,*) "B only."
CASE(B"10"); WRITE (6,*) "A only."
CASE(B"10"); WRITE (6,*) "A only."
CASE(B"11"); WRITE (6,*) "Both true."
CASE(B"11"); WRITE (6,*) "Both true."
END SELECT</lang>
END SELECT</syntaxhighlight>


But there is no extension to the allowed syntax, as such.
But there is no extension to the allowed syntax, as such.
Line 1,095: Line 1,095:


Note, as of 2019‑09‑04 this construct works only with a trunk FPC version.
Note, as of 2019‑09‑04 this construct works only with a trunk FPC version.
<lang pascal>program fourWay(input, output, stdErr);
<syntaxhighlight lang="pascal">program fourWay(input, output, stdErr);
var
var
tuple: record
tuple: record
Line 1,118: Line 1,118:
end;
end;
end;
end;
end.</lang>
end.</syntaxhighlight>


=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
<lang freebasic>' FB 1.05.0 Win64
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64


#Macro If2(condition1, condition2)
#Macro If2(condition1, condition2)
Line 1,152: Line 1,152:
Print
Print
Print "Press any key to quit"
Print "Press any key to quit"
Sleep</lang>
Sleep</syntaxhighlight>


{{out}}
{{out}}
Line 1,170: Line 1,170:
However, it's far less elegant. This is because, in Go, function arguments cannot be passed outside the method's parentheses and must be preceded by the func keyword.
However, it's far less elegant. This is because, in Go, function arguments cannot be passed outside the method's parentheses and must be preceded by the func keyword.


<lang go>package main
<syntaxhighlight lang="go">package main


import "fmt"
import "fmt"
Line 1,227: Line 1,227:
fmt.Println("a = 1 and b <> 3")
fmt.Println("a = 1 and b <> 3")
})
})
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 1,238: Line 1,238:
Expressions in Haskell are not evaluated until they are needed, so ordinary functions can be control structures.
Expressions in Haskell are not evaluated until they are needed, so ordinary functions can be control structures.


<lang haskell>if2 :: Bool -> Bool -> a -> a -> a -> a -> a
<syntaxhighlight lang="haskell">if2 :: Bool -> Bool -> a -> a -> a -> a -> a
if2 p1 p2 e12 e1 e2 e =
if2 p1 p2 e12 e1 e2 e =
if p1 then
if p1 then
Line 1,245: Line 1,245:


main = print $ if2 True False (error "TT") "TF" (error "FT") (error "FF")
main = print $ if2 True False (error "TT") "TF" (error "FT") (error "FF")
</syntaxhighlight>
</lang>


=={{header|Icon}} and {{header|Unicon}}==
=={{header|Icon}} and {{header|Unicon}}==
Line 1,253: Line 1,253:
(PDCO) may be defined and used. Here is an example:
(PDCO) may be defined and used. Here is an example:


<lang unicon>procedure main(A)
<syntaxhighlight lang="unicon">procedure main(A)
if2 { (A[1] = A[2]), (A[3] = A[4]), # Use PDCO with all three else clauses
if2 { (A[1] = A[2]), (A[3] = A[4]), # Use PDCO with all three else clauses
write("1: both true"),
write("1: both true"),
Line 1,272: Line 1,272:
else if @A[2] then |@\A[5]
else if @A[2] then |@\A[5]
else |@\A[6]
else |@\A[6]
end</lang>
end</syntaxhighlight>


and some sample runs:
and some sample runs:
Line 1,298: Line 1,298:
Idris provides the [http://docs.idris-lang.org/en/latest/tutorial/typesfuns.html#laziness Lazy] data type, which makes the computation of a parameter lazy.
Idris provides the [http://docs.idris-lang.org/en/latest/tutorial/typesfuns.html#laziness Lazy] data type, which makes the computation of a parameter lazy.


<lang idris>if2 : Bool -> Bool -> Lazy a -> Lazy a -> Lazy a -> Lazy a -> a
<syntaxhighlight lang="idris">if2 : Bool -> Bool -> Lazy a -> Lazy a -> Lazy a -> Lazy a -> a
if2 True True v _ _ _ = v
if2 True True v _ _ _ = v
if2 True False _ v _ _ = v
if2 True False _ v _ _ = v
if2 False True _ _ v _ = v
if2 False True _ _ v _ = v
if2 _ _ _ _ _ v = v</lang>
if2 _ _ _ _ _ v = v</syntaxhighlight>


=={{header|Inform 7}}==
=={{header|Inform 7}}==
Line 1,308: Line 1,308:
=== Statement ===
=== Statement ===
Inform 7 has two syntaxes for flow control blocks. Unfortunately, the newer indentation-based syntax only works with the built-in flow control statements, but it's possible to define new flow control statements using the older begin...end syntax:
Inform 7 has two syntaxes for flow control blocks. Unfortunately, the newer indentation-based syntax only works with the built-in flow control statements, but it's possible to define new flow control statements using the older begin...end syntax:
<lang inform7>To if2 (c1 - condition) and-or (c2 - condition) begin -- end: (- switch (({c1})*2 + ({c2})) { 3: do -).
<syntaxhighlight lang="inform7">To if2 (c1 - condition) and-or (c2 - condition) begin -- end: (- switch (({c1})*2 + ({c2})) { 3: do -).
To else1 -- in if2: (- } until (1); 2: do { -).
To else1 -- in if2: (- } until (1); 2: do { -).
To else2 -- in if2: (- } until (1); 1: do { -).
To else2 -- in if2: (- } until (1); 1: do { -).
To else0 -- in if2: (- } until (1); 0: -).</lang>
To else0 -- in if2: (- } until (1); 0: -).</syntaxhighlight>


Note that the "else0" part must be given, although "else1" and "else2" are optional. Demonstration:
Note that the "else0" part must be given, although "else1" and "else2" are optional. Demonstration:
<lang inform7>Home is a room.
<syntaxhighlight lang="inform7">Home is a room.


When play begins:
When play begins:
Line 1,325: Line 1,325:
else0;
else0;
say "neither";
say "neither";
end if2.</lang>
end if2.</syntaxhighlight>


=== Text substitution ===
=== Text substitution ===
<lang inform7>To say if2 (c1 - condition) and-or (c2 - condition) -- beginning if2:
<syntaxhighlight lang="inform7">To say if2 (c1 - condition) and-or (c2 - condition) -- beginning if2:
(- switch (({c1})*2 + ({c2})) { 3: -).
(- switch (({c1})*2 + ({c2})) { 3: -).
To say else1 -- continuing if2: (- 2: -).
To say else1 -- continuing if2: (- 2: -).
To say else2 -- continuing if2: (- 1: -).
To say else2 -- continuing if2: (- 1: -).
To say else0 -- continuing if2: (- 0: -).
To say else0 -- continuing if2: (- 0: -).
To say end if2 -- ending if2: (- } -).</lang>
To say end if2 -- ending if2: (- } -).</syntaxhighlight>


Demonstration:
Demonstration:
<lang inform7>Home is a room.
<syntaxhighlight lang="inform7">Home is a room.


When play begins:
When play begins:
say "[if2 the player is not in Home and-or the player is not a person]both[else1]only 1[else2]only 2[else0]neither[end if2]".</lang>
say "[if2 the player is not in Home and-or the player is not a person]both[else1]only 1[else2]only 2[else0]neither[end if2]".</syntaxhighlight>


=={{header|J}}==
=={{header|J}}==
Line 1,351: Line 1,351:
Here, we extend our language by defining a conjunction <code>if2</code> which consumes two nouns and produces a verb:
Here, we extend our language by defining a conjunction <code>if2</code> which consumes two nouns and produces a verb:


<lang j>if2=: 2 :0
<syntaxhighlight lang="j">if2=: 2 :0
'`b1 b2'=. n
'`b1 b2'=. n
m@.(b1 + 2 * b2) f.
m@.(b1 + 2 * b2) f.
)</lang>
)</syntaxhighlight>


Example use:
Example use:


<lang j>f0=: [: smoutput 'neither option: ' , ":
<syntaxhighlight lang="j">f0=: [: smoutput 'neither option: ' , ":
f1=: [: smoutput 'first option: ' , ":
f1=: [: smoutput 'first option: ' , ":
f2=: [: smoutput 'second option: ' , ":
f2=: [: smoutput 'second option: ' , ":
Line 1,371: Line 1,371:
both options: 2
both options: 2
first option: 3
first option: 3
second option: 4</lang>
second option: 4</syntaxhighlight>


That said, note that a switch statement which combines the boolean conditions as a base 2 number might be more convenient.
That said, note that a switch statement which combines the boolean conditions as a base 2 number might be more convenient.
Line 1,383: Line 1,383:
Java lambdas can go a long way towards allowing the implementation of lazy "branches", as this example shows.
Java lambdas can go a long way towards allowing the implementation of lazy "branches", as this example shows.


<lang java>
<syntaxhighlight lang="java">
public class If2 {
public class If2 {


Line 1,397: Line 1,397:
}
}
}
}
</syntaxhighlight>
</lang>


Usage:
Usage:


<lang java>
<syntaxhighlight lang="java">
import static If2.if2;
import static If2.if2;
class Main {
class Main {
Line 1,417: Line 1,417:
}
}
}
}
</syntaxhighlight>
</lang>


To allow optional else branches, and perhaps a more readable syntax with named branches, a more Object-Oriented approach can be used:
To allow optional else branches, and perhaps a more readable syntax with named branches, a more Object-Oriented approach can be used:


<lang java>
<syntaxhighlight lang="java">
public class If2 {
public class If2 {
private final boolean firstCondition;
private final boolean firstCondition;
Line 1,463: Line 1,463:
}
}
}
}
</syntaxhighlight>
</lang>


Usage (imports and main class ommited for brevity):
Usage (imports and main class ommited for brevity):


<lang java>
<syntaxhighlight lang="java">
// prints "both true"
// prints "both true"
if2(true, true)
if2(true, true)
Line 1,482: Line 1,482:
print("none true");
print("none true");
});
});
</syntaxhighlight>
</lang>


=={{header|Julia}}==
=={{header|Julia}}==
Julia has very powerful macros for metaprogramming. Code can be handled as a type of data in Julia. Julia macros are defined similarly to other functions, but are called with an '@' prior to the macro name, in order to distinguish macro calls from other function calls.
Julia has very powerful macros for metaprogramming. Code can be handled as a type of data in Julia. Julia macros are defined similarly to other functions, but are called with an '@' prior to the macro name, in order to distinguish macro calls from other function calls.
<lang julia>
<syntaxhighlight lang="julia">
const CSTACK1 = Array{Bool,1}()
const CSTACK1 = Array{Bool,1}()
const CSTACK2 = Array{Bool,1}()
const CSTACK2 = Array{Bool,1}()
Line 1,578: Line 1,578:


@elseifneither(begin println("neither") end)
@elseifneither(begin println("neither") end)
</syntaxhighlight>
</lang>
{{output}}<pre>
{{output}}<pre>
all
all
Line 1,588: Line 1,588:
=={{header|Kotlin}}==
=={{header|Kotlin}}==
Kotlin does not have macros or the like but, using a combination of chained functions and lambdas, it's possible to create something which closely resembles a language extension:
Kotlin does not have macros or the like but, using a combination of chained functions and lambdas, it's possible to create something which closely resembles a language extension:
<lang scala>// version 1.0.6
<syntaxhighlight lang="scala">// version 1.0.6


data class IfBoth(val cond1: Boolean, val cond2: Boolean) {
data class IfBoth(val cond1: Boolean, val cond2: Boolean) {
Line 1,640: Line 1,640:
println("a = 1 and b <> 3")
println("a = 1 and b <> 3")
}
}
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 1,650: Line 1,650:
=={{header|Lua}}==
=={{header|Lua}}==
Stricly speaking, Lua has no such capabilities. However, it could <i>perhaps</i> be approximated with a bit of trickery. This gets rather close to the suggested syntax, except for the long brackets. ("then2" is for parity with existing syntax)
Stricly speaking, Lua has no such capabilities. However, it could <i>perhaps</i> be approximated with a bit of trickery. This gets rather close to the suggested syntax, except for the long brackets. ("then2" is for parity with existing syntax)
<lang lua>-- Extend your language, in Lua, 6/17/2020 db
<syntaxhighlight lang="lua">-- Extend your language, in Lua, 6/17/2020 db
-- not to be taken seriously, ridiculous, impractical, esoteric, obscure, arcane ... but it works
-- not to be taken seriously, ridiculous, impractical, esoteric, obscure, arcane ... but it works


Line 1,690: Line 1,690:


end
end
end</lang>
end</syntaxhighlight>
{{out}}
{{out}}
<pre>i=1 j=1
<pre>i=1 j=1
Line 1,705: Line 1,705:
Lambdatalk comes with macros translating regular expressions into lambdatalk expressions
Lambdatalk comes with macros translating regular expressions into lambdatalk expressions


<syntaxhighlight lang="scheme">
<lang Scheme>
{macro \{if2 (true|false|\{[^{}]*\}) (true|false|\{[^{}]*\})\}
{macro \{if2 (true|false|\{[^{}]*\}) (true|false|\{[^{}]*\})\}
to {if {and $1 $2}
to {if {and $1 $2}
Line 1,724: Line 1,724:
{if2 {> 1 2} {< 3 4}} -> the second is true
{if2 {> 1 2} {< 3 4}} -> the second is true
{if2 {> 1 2} {> 3 4}} -> neither are true
{if2 {> 1 2} {> 3 4}} -> neither are true
</syntaxhighlight>
</lang>


=={{header|langur}}==
=={{header|langur}}==
Line 1,731: Line 1,731:
We could use the nxor (logical equivalence) operator to test truthiness.
We could use the nxor (logical equivalence) operator to test truthiness.


<lang langur>given .x nxor, .y nxor {
<syntaxhighlight lang="langur">given .x nxor, .y nxor {
case true: ... # both true
case true: ... # both true
case true, false: ... # first true, second false
case true, false: ... # first true, second false
case false, true: ... # first false, second true
case false, true: ... # first false, second true
default: ... # both false
default: ... # both false
}</lang>
}</syntaxhighlight>


To test directly for Boolean values (not truthiness), we could use the default == comparison.
To test directly for Boolean values (not truthiness), we could use the default == comparison.


<lang langur>given .x, .y {
<syntaxhighlight lang="langur">given .x, .y {
case true: ... # both true
case true: ... # both true
case true, false: ... # first true, second false
case true, false: ... # first true, second false
Line 1,746: Line 1,746:
case null, _: ... # first null, second irrelevant
case null, _: ... # first null, second irrelevant
default: ... # other
default: ... # other
}</lang>
}</syntaxhighlight>


=={{header|Lasso}}==
=={{header|Lasso}}==
Lasso doesn't allow you to define new keywords for the parser, but it does allow you to achieve a similar effect using captures and givenblock as illustrated below.
Lasso doesn't allow you to define new keywords for the parser, but it does allow you to achieve a similar effect using captures and givenblock as illustrated below.


<lang Lasso>// Create a type to handle the captures
<syntaxhighlight lang="lasso">// Create a type to handle the captures


define if2 => type {
define if2 => type {
Line 1,773: Line 1,773:
define else1 => thread_var_get(::if2)->else1 => givenblock
define else1 => thread_var_get(::if2)->else1 => givenblock
define else2 => thread_var_get(::if2)->else2 => givenblock
define else2 => thread_var_get(::if2)->else2 => givenblock
define else => thread_var_get(::if2)->else => givenblock</lang>
define else => thread_var_get(::if2)->else => givenblock</syntaxhighlight>


Example use:
Example use:


<lang Lasso>if2(true,true) => {
<syntaxhighlight lang="lasso">if2(true,true) => {
ifboth => {
ifboth => {
bothConditionsAreTrue
bothConditionsAreTrue
Line 1,790: Line 1,790:
noConditionIsTrue
noConditionIsTrue
}
}
}</lang>
}</syntaxhighlight>


=={{header|M2000 Interpreter}}==
=={{header|M2000 Interpreter}}==
Line 1,811: Line 1,811:
We can use nested if2 with same ctrl value, because ctrl programmed each time before a part block.
We can use nested if2 with same ctrl value, because ctrl programmed each time before a part block.


<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
module if2 {
module if2 {
over 3 : read &c
over 3 : read &c
Line 1,852: Line 1,852:
Print "ok"
Print "ok"


</syntaxhighlight>
</lang>


=={{header|m4}}==
=={{header|m4}}==
Line 1,858: Line 1,858:
See also [[#Plain_TeX|Plain TeX]].
See also [[#Plain_TeX|Plain TeX]].


<lang m4>divert(-1)
<syntaxhighlight lang="m4">divert(-1)


#
#
Line 1,878: Line 1,878:
ifelse2(1,1,2,-2,`exprxy',`exprx',`expry',`expr')
ifelse2(1,1,2,-2,`exprxy',`exprx',`expry',`expr')
ifelse2(1,-1,2,2,`exprxy',`exprx',`expry',`expr')
ifelse2(1,-1,2,2,`exprxy',`exprx',`expry',`expr')
ifelse2(1,-1,2,-2,`exprxy',`exprx',`expry',`expr')</lang>
ifelse2(1,-1,2,-2,`exprxy',`exprx',`expry',`expr')</syntaxhighlight>


{{out}}
{{out}}
Line 1,889: Line 1,889:
=={{header|Mathematica}} / {{header|Wolfram Language}}==
=={{header|Mathematica}} / {{header|Wolfram Language}}==
Mathematica is not precisely a Lisp, but it can easily construct macros by holding the arguments to a function:
Mathematica is not precisely a Lisp, but it can easily construct macros by holding the arguments to a function:
<syntaxhighlight lang="mathematica">
<lang Mathematica>
If2[test1_, test2_, condBoth_, cond1_, cond2_, condNone_] := With[
If2[test1_, test2_, condBoth_, cond1_, cond2_, condNone_] := With[
{result1 = test1,
{result1 = test1,
Line 1,899: Line 1,899:
True, condNone]];
True, condNone]];
SetAttributes[If2, HoldAll];
SetAttributes[If2, HoldAll];
</syntaxhighlight>
</lang>


Example usage (note that the tests are evaluated only once per call):
Example usage (note that the tests are evaluated only once per call):
<syntaxhighlight lang="mathematica">
<lang Mathematica>
x = 0;
x = 0;
If2[Mod[(++x), 2] == 0, Mod[x, 3] == 1, Print["Both: ", x], Print["First: ", x], Print["Second: ", x], Print["Neither: ", x]];
If2[Mod[(++x), 2] == 0, Mod[x, 3] == 1, Print["Both: ", x], Print["First: ", x], Print["Second: ", x], Print["Neither: ", x]];
Line 1,908: Line 1,908:
If2[Mod[(++x), 2] == 0, Mod[x, 3] == 1, Print["Both: ", x], Print["First: ", x], Print["Second: ", x], Print["Neither: ", x]];
If2[Mod[(++x), 2] == 0, Mod[x, 3] == 1, Print["Both: ", x], Print["First: ", x], Print["Second: ", x], Print["Neither: ", x]];
If2[Mod[(++x), 2] == 0, Mod[x, 3] == 1, Print["Both: ", x], Print["First: ", x], Print["Second: ", x], Print["Neither: ", x]];
If2[Mod[(++x), 2] == 0, Mod[x, 3] == 1, Print["Both: ", x], Print["First: ", x], Print["Second: ", x], Print["Neither: ", x]];
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,920: Line 1,920:
In min, <code>if</code> is simply a higher-order function that takes three quotations: a predicate and two branches. Likewise, <code>if2</code> is simply a higher-order function that takes six quotations: two predicates and four branches. No metaprogramming required.
In min, <code>if</code> is simply a higher-order function that takes three quotations: a predicate and two branches. Likewise, <code>if2</code> is simply a higher-order function that takes six quotations: two predicates and four branches. No metaprogramming required.
{{works with|min|0.27.1}}
{{works with|min|0.27.1}}
<lang min>(
<syntaxhighlight lang="min">(
:none :two :one :both -> :r2 -> :r1
:none :two :one :both -> :r2 -> :r1
(
(
Line 1,942: Line 1,942:
("false")
("false")
if puts! ;true
if puts! ;true
</syntaxhighlight>
</lang>


=={{header|Morfa}}==
=={{header|Morfa}}==
Morfa's operator defining and overloading can be employed to provide more natural syntax for expressing an <tt>if2</tt> "statement".
Morfa's operator defining and overloading can be employed to provide more natural syntax for expressing an <tt>if2</tt> "statement".
<lang morfa>
<syntaxhighlight lang="morfa">
import morfa.base;
import morfa.base;


Line 2,024: Line 2,024:
println("none true");
println("none true");
};
};
</syntaxhighlight>
</lang>


=={{header|Nemerle}}==
=={{header|Nemerle}}==
In file "if2macro.n":
In file "if2macro.n":
<syntaxhighlight lang="nemerle">
<lang Nemerle>
// point of interest: the when keyword and && operator inside the macro definition are macros themselves
// point of interest: the when keyword and && operator inside the macro definition are macros themselves


Line 2,040: Line 2,040:
when(!($cond1) && !($cond2)) {$bodyFF};
when(!($cond1) && !($cond2)) {$bodyFF};
]>
]>
}</lang>
}</syntaxhighlight>
Compile with:
Compile with:
<pre> ncc -r Nemerle.Compiler.dll -t:dll if2macro.n -o if2macro.dll</pre>
<pre> ncc -r Nemerle.Compiler.dll -t:dll if2macro.n -o if2macro.dll</pre>
In file useif2.n:
In file useif2.n:
<lang Nemerle>using System;
<syntaxhighlight lang="nemerle">using System;
using System.Console;
using System.Console;


Line 2,063: Line 2,063:
Write("You're unhappy, cheer up");
Write("You're unhappy, cheer up");
}
}
}</lang>
}</syntaxhighlight>
Compile with:<pre>ncc -r if2macro.dll useif2.n</pre>
Compile with:<pre>ncc -r if2macro.dll useif2.n</pre>


=={{header|NewLISP}}==
=={{header|NewLISP}}==


<lang NewLISP>(context 'if2)
<syntaxhighlight lang="newlisp">(context 'if2)


(define-macro (if2:if2 cond1 cond2 both-true first-true second-true neither)
(define-macro (if2:if2 cond1 cond2 both-true first-true second-true neither)
Line 2,091: Line 2,091:
> (if2 false false 'bothTrue 'firstTrue 'secondTrue 'else)
> (if2 false false 'bothTrue 'firstTrue 'secondTrue 'else)
else
else
</syntaxhighlight>
</lang>


=={{header|Nim}}==
=={{header|Nim}}==
<lang nim>import macros
<syntaxhighlight lang="nim">import macros
proc newIfElse(c, t, e: NimNode): NimNode {.compiletime.} =
proc newIfElse(c, t, e: NimNode): NimNode {.compiletime.} =
Line 2,155: Line 2,155:
echo "2"
echo "2"
else3:
else3:
echo "4"</lang>
echo "4"</syntaxhighlight>


=={{header|OCaml}}==
=={{header|OCaml}}==
Line 2,167: Line 2,167:
The same goes for pattern matchers in Lisps, such as the widely used public domain pattern matcher for Scheme.
The same goes for pattern matchers in Lisps, such as the widely used public domain pattern matcher for Scheme.


<lang ocaml>(* Languages with pattern matching ALREADY HAVE THIS! *)
<syntaxhighlight lang="ocaml">(* Languages with pattern matching ALREADY HAVE THIS! *)


let myfunc pred1 pred2 =
let myfunc pred1 pred2 =
Line 2,179: Line 2,179:
myfunc true false;;
myfunc true false;;
myfunc false true;;
myfunc false true;;
myfunc false false;;</lang>
myfunc false false;;</syntaxhighlight>


{{out}}
{{out}}
Line 2,190: Line 2,190:
=={{header|PARI/GP}}==
=={{header|PARI/GP}}==
Of course the language can be extended with GP functions (starting with version 2.4.2, these are closures).
Of course the language can be extended with GP functions (starting with version 2.4.2, these are closures).
<lang parigp>if2(c1,c2,tt,tf,ft,ff)={
<syntaxhighlight lang="parigp">if2(c1,c2,tt,tf,ft,ff)={
if(c1,
if(c1,
if(c2,tt,tf)
if(c2,tt,tf)
Line 2,196: Line 2,196:
if(c2,ft,ff)
if(c2,ft,ff)
)
)
};</lang>
};</syntaxhighlight>


GP can also be extended by adding C code directly to Pari:
GP can also be extended by adding C code directly to Pari:
<lang C>GEN
<syntaxhighlight lang="c">GEN
if2(GEN c1, GEN c2, GEN tt, GEN tf, GEN ft, GEN ff)
if2(GEN c1, GEN c2, GEN tt, GEN tf, GEN ft, GEN ff)
{
{
Line 2,212: Line 2,212:
else
else
return tt ? closure_evalgen(tt) : gnil;
return tt ? closure_evalgen(tt) : gnil;
}</lang>
}</syntaxhighlight>


This function, when compiled to the file <code>if2.gp.so</code>, can be loaded into GP with the following commands:
This function, when compiled to the file <code>if2.gp.so</code>, can be loaded into GP with the following commands:
<lang parigp>install("if2","GGDEDEDEDE","if2","./if2.gp.so");
<syntaxhighlight lang="parigp">install("if2","GGDEDEDEDE","if2","./if2.gp.so");
addhelp(if2, "if2(a,b,{seq1},{seq2},{seq3},{seq4}): if a is nonzero and b is nonzero, seq1 is evaluated; if a is nonzero and b is zero, seq2 is evaluated; if a is zero and b is nonzero, seq3 is evaluated; otherwise seq4. seq1 through seq4 are optional.");</lang>
addhelp(if2, "if2(a,b,{seq1},{seq2},{seq3},{seq4}): if a is nonzero and b is nonzero, seq1 is evaluated; if a is nonzero and b is zero, seq2 is evaluated; if a is zero and b is nonzero, seq3 is evaluated; otherwise seq4. seq1 through seq4 are optional.");</syntaxhighlight>
Alternately, add these lines into the C course and run through gp2c-run:
Alternately, add these lines into the C course and run through gp2c-run:
<syntaxhighlight lang="c">/*
<lang C>/*
GP;install("if2","GGDEDEDEDE","if2","./if2.gp.so");
GP;install("if2","GGDEDEDEDE","if2","./if2.gp.so");
GP;addhelp(if2, "if2(a,b,{seq1},{seq2},{seq3},{seq4}): if a is nonzero and b is nonzero, seq1 is evaluated; if a is nonzero and b is zero, seq2 is evaluated; if a is zero and b is nonzero, seq3 is evaluated; otherwise seq4. seq1 through seq4 are optional.");
GP;addhelp(if2, "if2(a,b,{seq1},{seq2},{seq3},{seq4}): if a is nonzero and b is nonzero, seq1 is evaluated; if a is nonzero and b is zero, seq2 is evaluated; if a is zero and b is nonzero, seq3 is evaluated; otherwise seq4. seq1 through seq4 are optional.");
*/</lang>
*/</syntaxhighlight>


=={{header|Perl}}==
=={{header|Perl}}==
Line 2,227: Line 2,227:
Closures enable user-defined control structures, but the syntax is not always identical to that of built-in control structures. This example is a start, but needs improving.
Closures enable user-defined control structures, but the syntax is not always identical to that of built-in control structures. This example is a start, but needs improving.


<lang perl>
<syntaxhighlight lang="perl">
#!/usr/bin/perl
#!/usr/bin/perl
use warnings;
use warnings;
Line 2,362: Line 2,362:


test_bits $_ for 0 .. 7;
test_bits $_ for 0 .. 7;
</syntaxhighlight>
</lang>


Sample run:
Sample run:


<lang>
<syntaxhighlight lang="text">
msl@64Lucid:~/perl$ ./if2
msl@64Lucid:~/perl$ ./if2
Testing 0: Neither bit is set
Testing 0: Neither bit is set
Line 2,377: Line 2,377:
Testing 7: Both bits 0 and 1 are set
Testing 7: Both bits 0 and 1 are set
msl@64Lucid:~/perl$
msl@64Lucid:~/perl$
</syntaxhighlight>
</lang>


=={{header|Phix}}==
=={{header|Phix}}==
Phix does not support macro programming. Generally I would suggest one of the following
Phix does not support macro programming. Generally I would suggest one of the following
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">switch</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">condition1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">condition2</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">switch</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">condition1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">condition2</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">case</span> <span style="color: #0000FF;">{</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">}:</span>
<span style="color: #008080;">case</span> <span style="color: #0000FF;">{</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">}:</span>
Line 2,388: Line 2,388:
<span style="color: #008080;">case</span> <span style="color: #0000FF;">{</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">}:</span>
<span style="color: #008080;">case</span> <span style="color: #0000FF;">{</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">}:</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
or
or
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">function</span> <span style="color: #000000;">if2</span><span style="color: #0000FF;">(</span><span style="color: #004080;">bool</span> <span style="color: #000000;">c1</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">bool</span> <span style="color: #000000;">c2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">if2</span><span style="color: #0000FF;">(</span><span style="color: #004080;">bool</span> <span style="color: #000000;">c1</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">bool</span> <span style="color: #000000;">c2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">c1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span><span style="color: #0000FF;">+</span><span style="color: #000000;">c2</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">c1</span><span style="color: #0000FF;">*</span><span style="color: #000000;">10</span><span style="color: #0000FF;">+</span><span style="color: #000000;">c2</span>
Line 2,401: Line 2,401:
<span style="color: #008080;">case</span> <span style="color: #000000;">00</span><span style="color: #0000FF;">:</span>
<span style="color: #008080;">case</span> <span style="color: #000000;">00</span><span style="color: #0000FF;">:</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
or
or
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">enum</span> <span style="color: #000000;">BOTH</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">FIRST</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">SECOND</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NEITHER</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b00</span>
<span style="color: #008080;">enum</span> <span style="color: #000000;">BOTH</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">FIRST</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">SECOND</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NEITHER</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b00</span>
Line 2,416: Line 2,416:
<span style="color: #008080;">elsif</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">=</span><span style="color: #000000;">NEITHER</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">=</span><span style="color: #000000;">NEITHER</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
I can accept that those could all be deemed cheating (and that the last does not look anywhere near as nice as I hoped it would).
I can accept that those could all be deemed cheating (and that the last does not look anywhere near as nice as I hoped it would).


Line 2,449: Line 2,449:
Next add new keywords. Find the last use of tt_stringF in pttree.e and add them. We do not know
Next add new keywords. Find the last use of tt_stringF in pttree.e and add them. We do not know
the ttidx values yet, so just duplicate the last one(5200)
the ttidx values yet, so just duplicate the last one(5200)
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">global</span> <span style="color: #008080;">constant</span> <span style="color: #000000;">T_if2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5200</span> <span style="color: #000000;">tt_stringF</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"if2"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_if2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">global</span> <span style="color: #008080;">constant</span> <span style="color: #000000;">T_if2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5200</span> <span style="color: #000000;">tt_stringF</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"if2"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_if2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">global</span> <span style="color: #008080;">constant</span> <span style="color: #000000;">T_else1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5200</span> <span style="color: #000000;">tt_stringF</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"else1"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_else1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">global</span> <span style="color: #008080;">constant</span> <span style="color: #000000;">T_else1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5200</span> <span style="color: #000000;">tt_stringF</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"else1"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_else1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">global</span> <span style="color: #008080;">constant</span> <span style="color: #000000;">T_else2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5200</span> <span style="color: #000000;">tt_stringF</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"else2"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_else2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">global</span> <span style="color: #008080;">constant</span> <span style="color: #000000;">T_else2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5200</span> <span style="color: #000000;">tt_stringF</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"else2"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_else2</span><span style="color: #0000FF;">)</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
Then run p p and it will tell you what they should be
Then run p p and it will tell you what they should be
<pre>
<pre>
Line 2,461: Line 2,461:
</pre>
</pre>
Update the values and rebuild the compiler using "p -cp" (approx 10 seconds), then we can add the latter two to the block terminators (in pmain.e):
Update the values and rebuild the compiler using "p -cp" (approx 10 seconds), then we can add the latter two to the block terminators (in pmain.e):
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--constant T_endelseelsif = {T_end,T_else,T_elsif,T_case,T_default,T_fallthru,T_fallthrough}</span>
<span style="color: #000080;font-style:italic;">--constant T_endelseelsif = {T_end,T_else,T_elsif,T_case,T_default,T_fallthru,T_fallthrough}</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">T_endelseelsif</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">T_end</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_else</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_else1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_else2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_elsif</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_case</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_default</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_fallthru</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_fallthrough</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">T_endelseelsif</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">T_end</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_else</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_else1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_else2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_elsif</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_case</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_default</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_fallthru</span><span style="color: #0000FF;">,</span><span style="color: #000000;">T_fallthrough</span><span style="color: #0000FF;">}</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
Admittedly the next part is non-trivial. Not really worthwhile showing here, the distribution
Admittedly the next part is non-trivial. Not really worthwhile showing here, the distribution
includes the file demo\rosetta\if2.txt which contains a DoIf2() procedure (120 lines) that
includes the file demo\rosetta\if2.txt which contains a DoIf2() procedure (120 lines) that
Line 2,470: Line 2,470:


Lastly, that would need to be hooked in, find the DoSwitch call (again in pmain.e) and insert after it:
Lastly, that would need to be hooked in, find the DoSwitch call (again in pmain.e) and insert after it:
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ttidx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">T_if2</span> <span style="color: #008080;">then</span> <span style="color: #000000;">DoIf2</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ttidx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">T_if2</span> <span style="color: #008080;">then</span> <span style="color: #000000;">DoIf2</span><span style="color: #0000FF;">()</span>
<!--</lang>-->
<!--</syntaxhighlight>-->


Recompile Phix (p -cp, approx 10s) and test.
Recompile Phix (p -cp, approx 10s) and test.
Obviously, while I have subsequently removed it, I have tried this myself and it worked fine:
Obviously, while I have subsequently removed it, I have tried this myself and it worked fine:
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">for</span> <span style="color: #000000;">N</span><span style="color: #0000FF;">=</span><span style="color: #000000;">10</span> <span style="color: #008080;">to</span> <span style="color: #000000;">20</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">N</span><span style="color: #0000FF;">=</span><span style="color: #000000;">10</span> <span style="color: #008080;">to</span> <span style="color: #000000;">20</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d is "</span><span style="color: #0000FF;">,</span><span style="color: #000000;">N</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d is "</span><span style="color: #0000FF;">,</span><span style="color: #000000;">N</span><span style="color: #0000FF;">)</span>
Line 2,489: Line 2,489:
<span style="color: #008080;">end</span> <span style="color: #000000;">if2</span>
<span style="color: #008080;">end</span> <span style="color: #000000;">if2</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
The equivalent changes that would be needed for pwa/p2js are left as an exercise for the reader, as above it would be largely a matter of figuring out what "switch" does and inserting a modified copy of that.
The equivalent changes that would be needed for pwa/p2js are left as an exercise for the reader, as above it would be largely a matter of figuring out what "switch" does and inserting a modified copy of that.
{{Out}}
{{Out}}
Line 2,507: Line 2,507:


=={{header|PHL}}==
=={{header|PHL}}==
<lang phl>module stmts;
<syntaxhighlight lang="phl">module stmts;


import phl::lang::io;
import phl::lang::io;
Line 2,559: Line 2,559:
println("Not this!");
println("Not this!");
];
];
]</lang>
]</syntaxhighlight>


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
<lang PicoLisp>(undef 'if2) # Undefine the built-in 'if2'
<syntaxhighlight lang="picolisp">(undef 'if2) # Undefine the built-in 'if2'


(de if2 "P"
(de if2 "P"
Line 2,569: Line 2,569:
(if (eval (car "P"))
(if (eval (car "P"))
(eval (cadddr "P"))
(eval (cadddr "P"))
(run (cddddr "P")) ) ) )</lang>
(run (cddddr "P")) ) ) )</syntaxhighlight>
Usage:
Usage:
<pre>(if2 (condition1isTrue) (condition2isTrue)
<pre>(if2 (condition1isTrue) (condition2isTrue)
Line 2,585: Line 2,585:
See also [[#m4|m4]].
See also [[#m4|m4]].


<lang plainTeX>\def\iftwo#1#2#3#4#5\elsefirst#6\elsesecond#7\elseneither#8\owtfi
<syntaxhighlight lang="plaintex">\def\iftwo#1#2#3#4#5\elsefirst#6\elsesecond#7\elseneither#8\owtfi
{\if#1#2\if#3#4#5\else#6\fi\else\if#3#4#7\else#8\fi\fi}
{\if#1#2\if#3#4#5\else#6\fi\else\if#3#4#7\else#8\fi\fi}


Line 2,597: Line 2,597:
\message{\iftwo{1}{-1}{2}{-2}\both\elsefirst\first\elsesecond\second\elseneither\neither\owtfi}
\message{\iftwo{1}{-1}{2}{-2}\both\elsefirst\first\elsesecond\second\elseneither\neither\owtfi}


\bye</lang>
\bye</syntaxhighlight>
{{out}}
{{out}}
<pre>$ tex extend_your_language.tex
<pre>$ tex extend_your_language.tex
Line 2,606: Line 2,606:


=={{header|PowerShell}}==
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function When-Condition
function When-Condition
{
{
Line 2,654: Line 2,654:
}
}
}
}
</syntaxhighlight>
</lang>
Full syntax:
Full syntax:
<syntaxhighlight lang="powershell">
<lang PowerShell>
When-Condition -Test1 (Test-Path .\temp.txt) -Test2 (Test-Path .\tmp.txt) `
When-Condition -Test1 (Test-Path .\temp.txt) -Test2 (Test-Path .\tmp.txt) `
-Both { "both true"
-Both { "both true"
Line 2,663: Line 2,663:
} -Neither { "neither true"
} -Neither { "neither true"
}
}
</syntaxhighlight>
</lang>
{{Out}}
{{Out}}
<pre>
<pre>
Line 2,669: Line 2,669:
</pre>
</pre>
Alternate syntax:
Alternate syntax:
<syntaxhighlight lang="powershell">
<lang PowerShell>
Set-Alias -Name if2 -Value When-Condition
Set-Alias -Name if2 -Value When-Condition


Line 2,678: Line 2,678:
} { "neither true"
} { "neither true"
}
}
</syntaxhighlight>
</lang>
{{Out}}
{{Out}}
<pre>
<pre>
Line 2,695: Line 2,695:
Note, however, that this is not a syntax extension. The following example is included merely for the sake of completeness.
Note, however, that this is not a syntax extension. The following example is included merely for the sake of completeness.


<lang python>a, b = 1, 0
<syntaxhighlight lang="python">a, b = 1, 0


if (c1 := a == 1) and (c2 := b == 3):
if (c1 := a == 1) and (c2 := b == 3):
Line 2,704: Line 2,704:
print('a <> 1 and b = 3')
print('a <> 1 and b = 3')
else:
else:
print('a <> 1 and b <> 3')</lang>
print('a <> 1 and b <> 3')</syntaxhighlight>


=={{header|Quackery}}==
=={{header|Quackery}}==
Line 2,710: Line 2,710:
Quackery is of the Forth family of languages and related to the Lisp family by marriage, so extensible control structures are a given. To this end it is equipped with ''meta-control'' words (the words in the code wrapped in reverse brackets) which grant control flow properties to words that use them. Code is given here for two possible syntaxes of a four-way IF.
Quackery is of the Forth family of languages and related to the Lisp family by marriage, so extensible control structures are a given. To this end it is equipped with ''meta-control'' words (the words in the code wrapped in reverse brackets) which grant control flow properties to words that use them. Code is given here for two possible syntaxes of a four-way IF.


<lang Quackery>( --------------------- version #1 --------------------- )
<syntaxhighlight lang="quackery">( --------------------- version #1 --------------------- )


[ not swap not 1 << |
[ not swap not 1 << |
Line 2,746: Line 2,746:
false true task.2
false true task.2
false false task.2
false false task.2
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 2,763: Line 2,763:
It is not possible to extend the language by adding keywords or creating macros. This kind of behaviour can be faked be creating functions that take expressions and evaluating them. (The switch and ifelse functions are existing examples.)
It is not possible to extend the language by adding keywords or creating macros. This kind of behaviour can be faked be creating functions that take expressions and evaluating them. (The switch and ifelse functions are existing examples.)


<syntaxhighlight lang="r">
<lang r>
if2 <- function(condition1, condition2, both_true, first_true, second_true, both_false)
if2 <- function(condition1, condition2, both_true, first_true, second_true, both_false)
{
{
Line 2,772: Line 2,772:
eval(expr)
eval(expr)
}
}
</syntaxhighlight>
</lang>


A test example:
A test example:
<syntaxhighlight lang="r">
<lang r>
for(x in 1:2) for(y in letters[1:2])
for(x in 1:2) for(y in letters[1:2])
{
{
Line 2,788: Line 2,788:
))
))
}
}
</syntaxhighlight>
</lang>


A variation that brings the syntax more in line with that described in the task is
A variation that brings the syntax more in line with that described in the task is
<syntaxhighlight lang="r">
<lang r>
if2 <- function(condition1, condition2, expr_list = NULL)
if2 <- function(condition1, condition2, expr_list = NULL)
{
{
Line 2,802: Line 2,802:
eval(cl[[cl_name]])
eval(cl[[cl_name]])
}
}
</syntaxhighlight>
</lang>


The usage here is modified to
The usage here is modified to
<syntaxhighlight lang="r">
<lang r>
for(x in 1:2) for(y in letters[1:2])
for(x in 1:2) for(y in letters[1:2])
{
{
Line 2,819: Line 2,819:
)))
)))
}
}
</syntaxhighlight>
</lang>


=={{header|Racket}}==
=={{header|Racket}}==
Line 2,825: Line 2,825:
Racket, like other Schemes, makes this kind of thing almost trivial:
Racket, like other Schemes, makes this kind of thing almost trivial:


<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
#lang racket
;; define a new syntax
;; define a new syntax
Line 2,854: Line 2,854:
(try 10 1) ; Second is small
(try 10 1) ; Second is small
(try 10 10) ; Neither is small
(try 10 10) ; Neither is small
</syntaxhighlight>
</lang>


But as usual, Racket takes this much more seriously. For example, here is how the same looks in an upcoming infix-style language in Racket:
But as usual, Racket takes this much more seriously. For example, here is how the same looks in an upcoming infix-style language in Racket:
Line 2,919: Line 2,919:


This solution is hygienic in both lexical and dynamic variables; the only caveat is that the user's program must avoid the dynamic variable being used by the implementation of conditional, <tt>$*IF2</tt>. This does not seem like a great hardship. (The conditionals will also nest correctly since that's how dynamic variables behave.)
This solution is hygienic in both lexical and dynamic variables; the only caveat is that the user's program must avoid the dynamic variable being used by the implementation of conditional, <tt>$*IF2</tt>. This does not seem like a great hardship. (The conditionals will also nest correctly since that's how dynamic variables behave.)
<lang perl6>my &if2 = -> \a, \b, &x { my @*IF2 = ?a,?b; x }
<syntaxhighlight lang="raku" line>my &if2 = -> \a, \b, &x { my @*IF2 = ?a,?b; x }


my &if-both = -> &x { x if @*IF2 eq (True,True) }
my &if-both = -> &x { x if @*IF2 eq (True,True) }
Line 2,939: Line 2,939:
}
}


say test |$_ for 1,0 X 1,0;</lang>
say test |$_ for 1,0 X 1,0;</syntaxhighlight>
{{out}}
{{out}}
<pre>Got both
<pre>Got both
Line 2,953: Line 2,953:


'''Usage example:'''
'''Usage example:'''
<lang rexx>if2( some-expression-that-results-in-a-boolean-value, some-other-expression-that-results-in-a-boolean-value)
<syntaxhighlight lang="rexx">if2( some-expression-that-results-in-a-boolean-value, some-other-expression-that-results-in-a-boolean-value)




Line 2,968: Line 2,968:
/*an example of a DO structure for the first clause: */
/*an example of a DO structure for the first clause: */


when if.11 /*{condition 1 & 2 are true}*/ then do; x=12; y=length(y); end</lang>
when if.11 /*{condition 1 & 2 are true}*/ then do; x=12; y=length(y); end</syntaxhighlight>
<lang rexx>/*REXX program introduces the IF2 "statement", a type of a four-way compound IF: */
<syntaxhighlight lang="rexx">/*REXX program introduces the IF2 "statement", a type of a four-way compound IF: */
parse arg bot top . /*obtain optional arguments from the CL*/
parse arg bot top . /*obtain optional arguments from the CL*/
if bot=='' | bot=="," then bot=10 /*Not specified? Then use the default.*/
if bot=='' | bot=="," then bot=10 /*Not specified? Then use the default.*/
Line 2,991: Line 2,991:
if.11= if.10 & if.01 /* " " case " 11 */
if.11= if.10 & if.01 /* " " case " 11 */
if.00= \(if.10 | if.01) /* " " " " 00 */
if.00= \(if.10 | if.01) /* " " " " 00 */
return ''</lang>
return ''</syntaxhighlight>
'''output'''
'''output'''
<pre>
<pre>
Line 3,013: Line 3,013:


=={{header|Ring}}==
=={{header|Ring}}==
<lang ring>
<syntaxhighlight lang="ring">
# Project : Extend your language
# Project : Extend your language


Line 3,037: Line 3,037:
ok
ok
see nl
see nl
</syntaxhighlight>
</lang>
Output:
Output:
<pre>
<pre>
Line 3,048: Line 3,048:
=={{header|Ruby}}==
=={{header|Ruby}}==
Ruby uses a hopelessly egocentric combinator (aka a combinator in which Kx = K for all x) and anonymous classes inherited from that combinator to do the job:
Ruby uses a hopelessly egocentric combinator (aka a combinator in which Kx = K for all x) and anonymous classes inherited from that combinator to do the job:
<lang ruby># Define a class which always returns itself for everything
<syntaxhighlight lang="ruby"># Define a class which always returns itself for everything
class HopelesslyEgocentric
class HopelesslyEgocentric
def method_missing(what, *args) self end
def method_missing(what, *args) self end
Line 3,070: Line 3,070:
end.new
end.new
end
end
end</lang>
end</syntaxhighlight>
Usage:
Usage:
<lang ruby>[true,false].product([true,false]).each do |cond1, cond2|
<syntaxhighlight lang="ruby">[true,false].product([true,false]).each do |cond1, cond2|
print "%5s, %5s => " % [cond1, cond2]
print "%5s, %5s => " % [cond1, cond2]
if2(cond1, cond2) do
if2(cond1, cond2) do
Line 3,083: Line 3,083:
puts "neither is true"
puts "neither is true"
end
end
end</lang>
end</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 3,093: Line 3,093:


=={{header|Rust}}==
=={{header|Rust}}==
<lang rust>#![allow(unused_variables)]
<syntaxhighlight lang="rust">#![allow(unused_variables)]
macro_rules! if2 {
macro_rules! if2 {
($cond1: expr, $cond2: expr
($cond1: expr, $cond2: expr
Line 3,123: Line 3,123:
=> println!("neither were true")
=> println!("neither were true")
)
)
}</lang>
}</syntaxhighlight>


=={{header|Scala}}==
=={{header|Scala}}==


Defining a new control construct:
Defining a new control construct:
<lang scala>scala> def if2[A](x: => Boolean)(y: => Boolean)(xyt: => A) = new {
<syntaxhighlight lang="scala">scala> def if2[A](x: => Boolean)(y: => Boolean)(xyt: => A) = new {
| def else1(xt: => A) = new {
| def else1(xt: => A) = new {
| def else2(yt: => A) = new {
| def else2(yt: => A) = new {
Line 3,144: Line 3,144:
| }
| }
if2: [A](x: => Boolean)(y: => Boolean)(xyt: => A)java.lang.Object{def else1(xt: => A): java.lang.Object{def else2(yt: =>
if2: [A](x: => Boolean)(y: => Boolean)(xyt: => A)java.lang.Object{def else1(xt: => A): java.lang.Object{def else2(yt: =>
A): java.lang.Object{def orElse(nt: => A): A}}}</lang>
A): java.lang.Object{def orElse(nt: => A): A}}}</syntaxhighlight>


Usage:
Usage:
<lang scala>scala> if2(true)(true) {
<syntaxhighlight lang="scala">scala> if2(true)(true) {
| 1
| 1
| } else1 {
| } else1 {
Line 3,167: Line 3,167:
| "Zoro"
| "Zoro"
| }
| }
res1: java.lang.String = Sanji</lang>
res1: java.lang.String = Sanji</syntaxhighlight>


=={{header|Scheme}}==
=={{header|Scheme}}==
<lang scheme>
<syntaxhighlight lang="scheme">
(define-syntax if2
(define-syntax if2
(syntax-rules ()
(syntax-rules ()
Line 3,178: Line 3,178:
(if c2 both-true first-true)
(if c2 both-true first-true)
(if c2 second-true none-true))))))
(if c2 second-true none-true))))))
</syntaxhighlight>
</lang>


=={{header|Seed7}}==
=={{header|Seed7}}==
Seed7 allows the definition of statement [http://seed7.sourceforge.net/manual/syntax.htm syntax] and semantic.
Seed7 allows the definition of statement [http://seed7.sourceforge.net/manual/syntax.htm syntax] and semantic.
<lang seed7>$ include "seed7_05.s7i";
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";


$ syntax expr: .if.().().then.().else1.().else2.().else3.().end.if is -> 25;
$ syntax expr: .if.().().then.().else1.().else2.().else3.().end.if is -> 25;
Line 3,220: Line 3,220:
writeln("error FALSE FALSE");
writeln("error FALSE FALSE");
end if;
end if;
end func;</lang>
end func;</syntaxhighlight>


=={{header|Shen}}==
=={{header|Shen}}==
Like most Lisps, this is trivial in Shen.
Like most Lisps, this is trivial in Shen.
<lang shen>(defmacro branch-if-macro
<syntaxhighlight lang="shen">(defmacro branch-if-macro
[branch-if Cond1 Cond2 Both Fst Snd None] ->
[branch-if Cond1 Cond2 Both Fst Snd None] ->
[if Cond1
[if Cond1
[if Cond2 Both Fst]
[if Cond2 Both Fst]
[if Cond2 Snd None]])</lang>
[if Cond2 Snd None]])</syntaxhighlight>
Example:
Example:
<lang shen>
<syntaxhighlight lang="shen">
(define try
(define try
X Y -> (branch-if (integer? X)
X Y -> (branch-if (integer? X)
Line 3,237: Line 3,237:


(map (/. X (do (print X) (nl)))
(map (/. X (do (print X) (nl)))
[(try 1 2) (try 1 1.5) (try 1.5 1) (try 1.5 1.5)])</lang>
[(try 1 2) (try 1 1.5) (try 1.5 1) (try 1.5 1.5)])</syntaxhighlight>


=={{header|Sidef}}==
=={{header|Sidef}}==
<lang ruby>class if2(cond1, cond2) {
<syntaxhighlight lang="ruby">class if2(cond1, cond2) {
method then(block) { # both true
method then(block) { # both true
if (cond1 && cond2) {
if (cond1 && cond2) {
Line 3,275: Line 3,275:
}.else {
}.else {
say "else"
say "else"
}</lang>
}</syntaxhighlight>
=={{header|Smalltalk}}==
=={{header|Smalltalk}}==
True method:&sup1; &sup2;
True method:&sup1; &sup2;
<lang smalltalk>or:condition2 ifBoth:bothBlk ifFirst:firstBlk ifSecond:scndBlk ifNone:noneBlk
<syntaxhighlight lang="smalltalk">or:condition2 ifBoth:bothBlk ifFirst:firstBlk ifSecond:scndBlk ifNone:noneBlk
"I know for sure, that I am true..."
"I know for sure, that I am true..."
^ condition2 ifTrue:bothBlk ifFalse:firstBlk</lang>
^ condition2 ifTrue:bothBlk ifFalse:firstBlk</syntaxhighlight>
False method:
False method:
<lang smalltalk>or:condition2 ifBoth:bothBlk ifFirst:firstBlk ifSecond:scndBlk ifNone:noneBlk
<syntaxhighlight lang="smalltalk">or:condition2 ifBoth:bothBlk ifFirst:firstBlk ifSecond:scndBlk ifNone:noneBlk
"I know for sure, that I am false..."
"I know for sure, that I am false..."
^ condition2 ifTrue:scndBlk ifFalse:noneBlk</lang>
^ condition2 ifTrue:scndBlk ifFalse:noneBlk</syntaxhighlight>


You can now write:
You can now write:
<lang smalltalk>(a > 0) or:(b > 10)
<syntaxhighlight lang="smalltalk">(a > 0) or:(b > 10)
ifBoth:[ 'both' printCR]
ifBoth:[ 'both' printCR]
ifFirst:[ 'only first' printCR ]
ifFirst:[ 'only first' printCR ]
ifSecond:[ 'only second' printCR ]
ifSecond:[ 'only second' printCR ]
ifNone: [ 'none' printCR ]</lang>
ifNone: [ 'none' printCR ]</syntaxhighlight>


Note 1: you may have noticed, that the normal "ifTrue:" methods look very similar. That is because they are implemented exactly the same way - in Smalltalk, there is no syntax; all is done via this kind of method dispatch (in this case to the true or false object).<br>Note 2: I could have named the keywords "else1:", "else2:", "else:", but in Smalltalk it is good practice to give them more descriptive names).
Note 1: you may have noticed, that the normal "ifTrue:" methods look very similar. That is because they are implemented exactly the same way - in Smalltalk, there is no syntax; all is done via this kind of method dispatch (in this case to the true or false object).<br>Note 2: I could have named the keywords "else1:", "else2:", "else:", but in Smalltalk it is good practice to give them more descriptive names).
Line 3,297: Line 3,297:
It would also be possible to define a dummy class named "If2" and there a class method (aka static method).
It would also be possible to define a dummy class named "If2" and there a class method (aka static method).
<br>But I'd like to mention that this is considered very bad style (polluting the class namespace with such stuff):
<br>But I'd like to mention that this is considered very bad style (polluting the class namespace with such stuff):
<lang smalltalk>If2 class method:
<syntaxhighlight lang="smalltalk">If2 class method:
when:cond1 or:cond2 ifBoth:both ifFirst:first ifSecond:scnd ifNone:none
when:cond1 or:cond2 ifBoth:both ifFirst:first ifSecond:scnd ifNone:none
^ cond1 ifTrue:[
^ cond1 ifTrue:[
Line 3,303: Line 3,303:
] ifFalse:[
] ifFalse:[
cond2 ifTrue:scnd ifFalse:none
cond2 ifTrue:scnd ifFalse:none
]</lang>
]</syntaxhighlight>
Now, you can write:
Now, you can write:
<lang smalltalk>If2 when:(a > 0) or:(b > 10)
<syntaxhighlight lang="smalltalk">If2 when:(a > 0) or:(b > 10)
ifBoth:[ 'both' printCR]
ifBoth:[ 'both' printCR]
ifFirst:[ 'only first' printCR ]
ifFirst:[ 'only first' printCR ]
ifSecond:[ 'only second' printCR ]
ifSecond:[ 'only second' printCR ]
ifNone: [ 'none' printCR ]</lang>
ifNone: [ 'none' printCR ]</syntaxhighlight>


=={{header|Standard ML}}==
=={{header|Standard ML}}==
Line 3,315: Line 3,315:
See also [[#ATS|ATS]] and [[#OCaml|OCaml]].
See also [[#ATS|ATS]] and [[#OCaml|OCaml]].


<lang sml>(* Languages with pattern matching ALREADY HAVE THIS! *)
<syntaxhighlight lang="sml">(* Languages with pattern matching ALREADY HAVE THIS! *)


fun myfunc (pred1, pred2) =
fun myfunc (pred1, pred2) =
Line 3,327: Line 3,327:
myfunc (true, false);
myfunc (true, false);
myfunc (false, true);
myfunc (false, true);
myfunc (false, false);</lang>
myfunc (false, false);</syntaxhighlight>


{{out}}
{{out}}
Line 3,338: Line 3,338:
=={{header|Tcl}}==
=={{header|Tcl}}==
The core of Tcl's language-level extensibility are the <code>uplevel</code> and <code>upvar</code> commands, which respectively allow execution of arbitrary code in the caller's context and provide safe access to variables in the caller's context. To create an <code>if2</code>, only <code>uplevel</code> is required (together with <code>list</code> which does substitution-safe script generation as a side-effect):
The core of Tcl's language-level extensibility are the <code>uplevel</code> and <code>upvar</code> commands, which respectively allow execution of arbitrary code in the caller's context and provide safe access to variables in the caller's context. To create an <code>if2</code>, only <code>uplevel</code> is required (together with <code>list</code> which does substitution-safe script generation as a side-effect):
<lang tcl>proc if2 {cond1 cond2 bothTrueBody firstTrueBody secondTrueBody bothFalseBody} {
<syntaxhighlight lang="tcl">proc if2 {cond1 cond2 bothTrueBody firstTrueBody secondTrueBody bothFalseBody} {
# Must evaluate both conditions, and should do so in order
# Must evaluate both conditions, and should do so in order
set c1 [uplevel 1 [list expr $cond1]
set c1 [uplevel 1 [list expr $cond1]
Line 3,352: Line 3,352:
uplevel 1 $bothFalseBody
uplevel 1 $bothFalseBody
}
}
}</lang>
}</syntaxhighlight>
Demonstrating:
Demonstrating:
<lang tcl>if2 {1 > 0} {"grill" in {foo bar boo}} {
<syntaxhighlight lang="tcl">if2 {1 > 0} {"grill" in {foo bar boo}} {
puts "1 and 2"
puts "1 and 2"
} {
} {
Line 3,362: Line 3,362:
} {
} {
puts "neither 1 nor 2"
puts "neither 1 nor 2"
}</lang>
}</syntaxhighlight>
Which produces this output:
Which produces this output:
<pre>1 but not 2</pre>
<pre>1 but not 2</pre>
=== Condition-free form ===
=== Condition-free form ===
It's also possible to write this without any use of <code>if</code> at all, through the careful selection of variable names:
It's also possible to write this without any use of <code>if</code> at all, through the careful selection of variable names:
<lang tcl>proc if2 {cond1 cond2 body00 body01 body10 body11} {
<syntaxhighlight lang="tcl">proc if2 {cond1 cond2 body00 body01 body10 body11} {
# Must evaluate both conditions, and should do so in order
# Must evaluate both conditions, and should do so in order
# Extra negations ensure boolean interpretation
# Extra negations ensure boolean interpretation
Line 3,374: Line 3,374:
# Use those values to pick the script to evaluate
# Use those values to pick the script to evaluate
uplevel 1 [set body$c1$c2]
uplevel 1 [set body$c1$c2]
}</lang>
}</syntaxhighlight>
This behaves exactly as above, so shall not be repeated here.
This behaves exactly as above, so shall not be repeated here.
=== Other language extension forms ===
=== Other language extension forms ===
Tcl includes very strong support for language extension. For example, consider this code which implements a integer looping command:
Tcl includes very strong support for language extension. For example, consider this code which implements a integer looping command:
<lang tcl>proc loop {varName lowerBound upperBound body} {
<syntaxhighlight lang="tcl">proc loop {varName lowerBound upperBound body} {
upvar 1 $varName var
upvar 1 $varName var
for {set var $lowerBound} {$var <= $upperBound} {incr var} {
for {set var $lowerBound} {$var <= $upperBound} {incr var} {
uplevel 1 $body
uplevel 1 $body
}
}
}</lang>
}</syntaxhighlight>
That implements, in a few lines of code, a new looping construct that does integer iteration and which supports both <code>break</code> and <code>continue</code>, as any loop should. The loop variable is “owned” by the context which calls the loop, and the loop body can access all local variables. It's all also completely safe against complex substitutions. Here's an example of use:
That implements, in a few lines of code, a new looping construct that does integer iteration and which supports both <code>break</code> and <code>continue</code>, as any loop should. The loop variable is “owned” by the context which calls the loop, and the loop body can access all local variables. It's all also completely safe against complex substitutions. Here's an example of use:
<lang tcl>proc timestables {M N} {
<syntaxhighlight lang="tcl">proc timestables {M N} {
loop i 1 $M {
loop i 1 $M {
loop j 1 $N {
loop j 1 $N {
Line 3,392: Line 3,392:
}
}
}
}
timestables 3 3</lang>
timestables 3 3</syntaxhighlight>
Output:
Output:
<pre>
<pre>
Line 3,410: Line 3,410:
{{trans|CommonLisp}}
{{trans|CommonLisp}}


<lang txrlisp>(defmacro if2 (cond1 cond2 both first second . neither)
<syntaxhighlight lang="txrlisp">(defmacro if2 (cond1 cond2 both first second . neither)
(let ((res1 (gensym))
(let ((res1 (gensym))
(res2 (gensym)))
(res2 (gensym)))
Line 3,418: Line 3,418:
(,res1 ,first)
(,res1 ,first)
(,res2 ,second)
(,res2 ,second)
(t ,*neither)))))</lang>
(t ,*neither)))))</syntaxhighlight>


=={{header|UNIX Shell}}==
=={{header|UNIX Shell}}==
Line 3,424: Line 3,424:


{{works with|Bourne Shell}}
{{works with|Bourne Shell}}
<lang bash>if2() {
<syntaxhighlight lang="bash">if2() {
if eval "$1"; then
if eval "$1"; then
if eval "$2"; then eval "$3"; else eval "$4"; fi
if eval "$2"; then eval "$3"; else eval "$4"; fi
Line 3,430: Line 3,430:
if eval "$2"; then eval "$5"; else eval "$6"; fi
if eval "$2"; then eval "$5"; else eval "$6"; fi
fi
fi
}</lang>
}</syntaxhighlight>


<lang bash>if2 'test 7 -lt 9' 'test 7 -gt 9' '
<syntaxhighlight lang="bash">if2 'test 7 -lt 9' 'test 7 -gt 9' '
echo both 1 and 2
echo both 1 and 2
' '
' '
Line 3,440: Line 3,440:
' '
' '
echo neither 1 nor 2
echo neither 1 nor 2
'</lang>
'</syntaxhighlight>


==={{header|es}}===
==={{header|es}}===
{{trans|Tcl}}
{{trans|Tcl}}
<lang es>fn if2 cond1 cond2 body11 body10 body01 body00 {
<syntaxhighlight lang="es">fn if2 cond1 cond2 body11 body10 body01 body00 {
# Must evaluate both conditions, and should do so in order.
# Must evaluate both conditions, and should do so in order.
# Negation ensures a boolean result: a true condition becomes
# Negation ensures a boolean result: a true condition becomes
Line 3,452: Line 3,452:
$(body$c1$c2)
$(body$c1$c2)
}
}
}</lang>
}</syntaxhighlight>


<lang es>if2 {test 1 -gt 0} {~ grill foo bar boo} {
<syntaxhighlight lang="es">if2 {test 1 -gt 0} {~ grill foo bar boo} {
echo 1 and 2
echo 1 and 2
} {
} {
Line 3,462: Line 3,462:
} {
} {
echo neither 1 nor 2
echo neither 1 nor 2
}</lang>
}</syntaxhighlight>


=={{header|Ursala}}==
=={{header|Ursala}}==
Identifiers can't contain digits, so the function is named <code>iftwo</code>.
Identifiers can't contain digits, so the function is named <code>iftwo</code>.
<lang Ursala>iftwo("p","q") <"both","justp","justq","neither"> =
<syntaxhighlight lang="ursala">iftwo("p","q") <"both","justp","justq","neither"> =


"p"?(
"p"?(
"q"?("both","justp"),
"q"?("both","justp"),
"q"?("justq","neither"))</lang>
"q"?("justq","neither"))</syntaxhighlight>
The type of <code>iftwo</code> is that of a function taking a pair of predicates and
The type of <code>iftwo</code> is that of a function taking a pair of predicates and
returning a function that takes a list of four functions. A function of the form
returning a function that takes a list of four functions. A function of the form
Line 3,482: Line 3,482:
{{trans|Kotlin}}
{{trans|Kotlin}}
Like Kotlin Wren does not have macros but, using a combination of chained functions and methods, it's possible (if you squint a little) to create something which closely resembles a language extension.
Like Kotlin Wren does not have macros but, using a combination of chained functions and methods, it's possible (if you squint a little) to create something which closely resembles a language extension.
<lang ecmascript>class IfBoth {
<syntaxhighlight lang="ecmascript">class IfBoth {
construct new(cond1, cond2) {
construct new(cond1, cond2) {
_cond1 = cond1
_cond1 = cond1
Line 3,533: Line 3,533:
}.elseFirst {
}.elseFirst {
System.print("a == 1 and b <> 3")
System.print("a == 1 and b <> 3")
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 3,543: Line 3,543:
=={{header|XBS}}==
=={{header|XBS}}==
In XBS you are allowed to define custom syntax. The only real purpose for this is quick development or testing.
In XBS you are allowed to define custom syntax. The only real purpose for this is quick development or testing.
<lang xbs>#>
<syntaxhighlight lang="xbs">#>
newsyntax
newsyntax
@in:CH
@in:CH
Line 3,627: Line 3,627:
equalsOneOrTwo(2);
equalsOneOrTwo(2);
equalsOneOrTwo(3);
equalsOneOrTwo(3);
equalsOneOrTwo(0);</lang>
equalsOneOrTwo(0);</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 3,638: Line 3,638:
=={{header|Z80 Assembly}}==
=={{header|Z80 Assembly}}==
The language can only really be extended using macros, since there's no way to add your own commands. This is a simple template for a 4 way branch. It's not the most elegant method, but it gets the job done.
The language can only really be extended using macros, since there's no way to add your own commands. This is a simple template for a 4 way branch. It's not the most elegant method, but it gets the job done.
<lang z80>cp b
<syntaxhighlight lang="z80">cp b
jr nz,B_False
jr nz,B_False
cp c
cp c
Line 3,664: Line 3,664:


done:
done:
;rest of program</lang>
;rest of program</syntaxhighlight>




Line 3,670: Line 3,670:
The only way to formally create additional commands for ZX Spectrum Basic is by attaching an Interface 1 and defining the command in machine code. However, we can work with the fact that boolean comparisons are evaluated numerically by defining a new function with the value table.
The only way to formally create additional commands for ZX Spectrum Basic is by attaching an Interface 1 and defining the command in machine code. However, we can work with the fact that boolean comparisons are evaluated numerically by defining a new function with the value table.


<lang zxbasic>10 DEF FN i()=((NOT (a OR b))+2*(a AND NOT b)+3*(b AND NOT a)+4*(a AND b)): REM the function can be placed anywhere in the program, but it gets executed faster if it's at the top
<syntaxhighlight lang="zxbasic">10 DEF FN i()=((NOT (a OR b))+2*(a AND NOT b)+3*(b AND NOT a)+4*(a AND b)): REM the function can be placed anywhere in the program, but it gets executed faster if it's at the top
20 FOR x=1 TO 20
20 FOR x=1 TO 20
30 LET a=(x/2)=INT (x/2): REM comparison 1
30 LET a=(x/2)=INT (x/2): REM comparison 1
Line 3,679: Line 3,679:
80 PRINT x;" is divisible by 3": GO TO 100
80 PRINT x;" is divisible by 3": GO TO 100
90 PRINT x;" is divisible by 2 and 3"
90 PRINT x;" is divisible by 2 and 3"
100 NEXT x</lang>
100 NEXT x</syntaxhighlight>
{{out}}
{{out}}
<pre>1 is not divisible by 2 or 3
<pre>1 is not divisible by 2 or 3