Extend your language: Difference between revisions

 
(35 intermediate revisions by 12 users not shown)
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.
=={{header|ABAP}}==
<langsyntaxhighlight lang="abap">DATA(result) = COND #( WHEN condition1istrue = abap_true AND condition2istrue = abap_true THEN bothconditionsaretrue
WHEN condition1istrue = abap_true THEN firstconditionistrue
WHEN condition2istrue = abap_true THEN secondconditionistrue
ELSE noconditionistrue ).
</syntaxhighlight>
</lang>
=={{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.
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.
 
<langsyntaxhighlight lang="6502asm">CMP_Double .macro ;NESASM3 syntax
; input:
; \1 = first condition. Valid addressing modes: immediate, zero page, or absolute.
Line 65:
.doublefalse:
JMP \6 ;both are false
.endm</langsyntaxhighlight>
 
=={{header|68000 Assembly}}==
The 68000 actually has hardware support for extending the language, using the vector table. The "Line A Emulator" vector will trap any instruction that begins with the bit pattern "1010", as no 68000 instruction begins with those bits. This allows you to effectively create your own instructions using a handler that can look at the instruction that caused the trap and decode the rest of it by looking at the other bits. This process is slow, and won't be used for this task, but is worth a mention as it allows for forward compatibility with later versions of the M680x0 CPU family.
 
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.
 
<syntaxhighlight lang="68000devpac">macro if2_EQ_DOT_L 1,2,3,4
;input: 1 = first param (can be any addressing mode compatible with CMP)
; 2 = second param (used for condition 1)
; 3 = third param (used for condition 2)
; 4 = output for comparison results (must be a data register, and can't be 1, 2, or 3. The macro will not enforce this!)
 
; <backslash>@ represents a macro-local label that is scoped for each instance of that macro in your program
; and doesn't cause "label already defined" conflicts if the macro is used multiple times
 
MOVEQ #0,\4
CMP.L \2,\1
BEQ \@eqCond1
;condition 1 failed.
CMP.L \3,\1
BEQ \@TwoButNotOne
;both failed
clr.b d0
bra \@done
\@eqCond1:
CMP.L \3,\1
BEQ \@Both
move.b #2,d0
bra \@done
\@Both:
move.b #3,d0
bra \@done
\@TwoButNotOne:
move.b #1,d0
\@done:
endm</syntaxhighlight>
=={{header|Ada}}==
 
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO; use Ada.Text_IO;
 
procedure Test_If_2 is
Line 88 ⟶ 123:
end case;
end loop;
end Test_If_2;</langsyntaxhighlight>
 
{{out}}
Line 108 ⟶ 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.
 
<langsyntaxhighlight lang="agda">
 
data Bool : Set where
Line 126 ⟶ 161:
example : Bool
example = if2 true , false then true else1 false else2 true else false
</syntaxhighlight>
</lang>
 
=={{header|ALGOL 68}}==
<langsyntaxhighlight lang="algol68"># operator to turn two boolean values into an integer - name inspired by the COBOL sample #
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;
Line 141 ⟶ 176:
, print( ( "second: only b is TRUE", newline ) )
, print( ( "neither: a and b are FALSE", newline ) )
ESAC</langsyntaxhighlight>
 
=={{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).
<langsyntaxhighlight lang="algolw">begin
% executes pBoth, p1, p2 or pNeither %
% depending on whether c1 and c2 are true, c1 is true, c2 is true %
Line 168 ⟶ 203:
)
end
end.</langsyntaxhighlight>
 
=={{header|Amazing Hopper}}==
<p>HOPPER permite definir muchas extensiones del lenguaje a través de su potentísimo preprocesador. A continuación, veremos un par de ejemplos.</p>
<p>OBSERVACION: Se puede preguntar por opciones falsas, reemplazando "JNT" (Jump if Not True) por "JT" (Jump if True".</p>
 
Ejemplo #1:
<syntaxhighlight lang="bennugd">
#include <jambo.h>
 
#defn Siambassonverdaderas(_X_,_Y_) ##CODEIF,__firstop__=0;#ATOM#CMPLX;cpy(__firstop__),\
__secondop__=0;#ATOM#CMPLX;cpy(__secondop__);\
and;jnt(#ENDIF),
#defn Essólolaprimeraopción jmp(%%CODEIF), %ENDIF:, {__firstop__}, jnt(#ENDIF),
#defn Essólolasegundaopción jmp(%%CODEIF), %ENDIF:, {__secondop__}, jnt(#ENDIF),
#synon Else Noesningunaopción?
#synon EndIf FindelSi
 
Main
False(v), True(w)
Si ambas son verdaderas ( v, w )
Printnl ("Son ambas opciones verdaderas")
 
Es sólo la primera opción
Printnl ("La primera opción es verdadera")
 
Es sólo la segunda opción
Printnl ("La segunda opción es verdadera")
 
No es ninguna opción?
Printnl ("Nada se cumple")
Fin del Si
 
End</syntaxhighlight>
{{out}}
<pre>La segunda opción es verdadera</pre>
 
<p>Ejemplo #2:</p>
<p>El preprocesador de HOPPER permite extender la estructura "IF" (o "SI" es español), a cualquier número de expresiones lógicas como opción:
</p>
<syntaxhighlight lang="bennugd">
#include <jambo.h>
 
#defn Sitodassonverdaderas(*) ##CODEIF,{1},#GENCODE $$$*$$$ opción#ITV=0;#ATCMLIST;\
cpy(opción#ITV);and;#ENDGEN;,jnt(#ENDIF)
#synon Sitodassonverdaderas Sitodaslasopciones,Sitodasestas,Sitodas
#defn Sonverdaderas(*) jmp(%%CODEIF), %ENDIF:, {1}, #GENCODE $$$*$$$ #ATCMLIST;\
and;#ENDGEN;jnt(#ENDIF),
#defn Esla(_X_) jmp(%%CODEIF), %ENDIF:, {_X_}, jnt(#ENDIF),
#defn Esverdaderalaopción(_X_) jmp(%%CODEIF), %ENDIF:, {opción_X_}, jnt(#ENDIF),
#defn Sonverdaderaslasopciones(*) jmp(%%CODEIF), %ENDIF:,{1};#GENCODE $$$*$$$ {opción#LIST};\
and;#ENDGEN;jnt(#ENDIF),
#synon Sonverdaderaslasopciones Sonlasopciones
#synon Else Noesningunaopción?
#synon EndIf FindelSi
#define verdadera? ;
#synon verdadera? verdaderas?,verdadera,verdaderas,sonverdaderas,esverdadera
 
Main
True(v), True(x), True(y)
Si todas estas 'v, {0.025} Is equal to (10), x, y' son verdaderas
Set ("Todas las opciones son verdaderas")
 
Son verdaderas 'opción 2, opción 3, opción 4'
Set ("Sólo son verdaderas la igualdad, X e Y")
 
Son verdaderas las opciones '1,3,4'
Set ("Son verdaderas V, X e Y")
 
Son las opciones '1,3,4' verdaderas?
Set ("Son verdaderas V, X e Y")
 
Son verdaderas 'opción 1, opción 3'
Set ("Son verdaderas V y X")
 
/* podríamos seguir preguntando... */
 
Es verdadera la opción '2'
Set ("Al menos, la igualdad es verdadera")
 
Es la 'opción 4' verdadera?
Set ("Al menos, Y es verdadera")
 
No es ninguna opción?
Set ("Nada se cumple")
 
Fin del Si
Prnl
End
</syntaxhighlight>
{{out}}
<pre>Son verdaderas V, X e Y</pre>
 
<p>Ejemplo #3:</p>
<p>Aquí sólo la macro "»" que significa "CPY" (copia el valor de memoria a la variable indicada pero sin removerlo) permite extender el uso de "IF" (que también es una macro que extiende el lenguaje base), de acuerdo al ejemplo:</p>
<syntaxhighlight lang="bennugd">
#include <jambo.h>
 
Main
True(v), False(w), first option=0, second option=0
If ( var 'v' » 'first option', And ( w » 'second option' ) )
Printnl ("Son ambas opciones verdaderas")
 
Else If ( first option )
Printnl ("La primera opción es verdadera")
 
Else If ( second option )
Printnl ("La segunda opción es verdadera")
Else
Printnl ("Ninguna es verdadera")
End If
End
</syntaxhighlight>
{{out}}
<pre>La primera opción es verdadera</pre>
=== google translation ===
<pre>
HOPPER allows you to define many language extensions through its very powerful preprocessor. Next, we will see a couple of examples.
 
NOTE: You can ask for false options, replacing "JNT" (Jump if Not True) with "JT" (Jump if True).
 
NOTE 2: These examples are executable in HOPPER, because HOPPER allows you to define "flavors" of programming languages ​​in any language (respecting the use of the character " ' " as a synonym for parentheses).
 
Example 1:
 
#include <jambo.h>
 
#defn Ifbotharetrue(_X_,_Y_) ##CODEIF,__firstop__=0;#ATOM#CMPLX;cpy(__firstop__),\
__secondop__=0;#ATOM#CMPLX;cpy(__secondop__);\
and;jnt(#ENDIF),
#defn Itisonlythefirstoption jmp(%%CODEIF), %ENDIF:, {__firstop__}, jnt(#ENDIF),
#defn Itisonlythesecondoption jmp(%%CODEIF), %ENDIF:, {__secondop__}, jnt(#ENDIF),
#synon Else Isnotthereanoption?
 
Main
False(v), True(w)
If both are true ( v, w )
Printnl("Both options are true")
 
It is only the first option
Printnl("The first option is true")
 
It is only the second option
Printnl("The second option is true")
 
Is not there an option?
Printnl ("Nothing is fulfilled")
End If
 
End
 
Output:
 
The second option is true
 
Example #2:
 
The HOPPER preprocessor allows you to extend the "IF" (or "SI" in Spanish) structure, to any number of logical expressions as an option:
 
#include <jambo.h>
 
#defn Ifallaretrue(*) ##CODEIF,{1},#GENCODE $$$*$$$ option#ITV=0;#ATCMLIST;\
cpy(#ITV option);and;#ENDGEN;,jnt(#ENDIF)
#synon Ifallaretrue Ifalloptions, Ifallofthese, Ifall
#defn Aretrue(*) jmp(%%CODEIF), %ENDIF:, {1}, #GENCODE $$$*$$$ #ATCMLIST;\
and;#ENDGEN;jnt(#ENDIF),
#synon Aretrue Theyaretrue
#defn Is(_X_) jmp(%%CODEIF), %ENDIF:, {_X_}, jnt(#ENDIF),
#defn Option(_X_) jmp(%%CODEIF), %ENDIF:, {option_X_}, jnt(#ENDIF),
#defn Aretheoptions(*) jmp(%%CODEIF), %ENDIF:,{1};#GENCODE $$$*$$$ {option#LIST};\
and;#ENDGEN;jnt(#ENDIF),
#synon Aretheoptions Theoptions
#synon Else Isnotthereanoption?
#define true? ;
#synon true? true, aretrue?, aretrue, istrue
 
Main
True(v), True(x), True(y)
If all of these 'v, {0.025} Is equal to (10), x, y' are true
Set("All options are true")
 
Are true 'option 2, option 3, option 4'
Set ("Only equality, X and Y are true")
 
The options '1,3,4' are true
Set("V, X and Y are true")
 
Are the options '1,3,4' true?
Set("V, X and Y are true")
 
They are true 'option 1, option 3'
Set("V and X are true")
 
/* we could keep asking... */
 
Option '2' is true
Set("At least, equality is true")
 
Is 'option 4' true?
Set ("At least, Y is true")
 
Is not there an option?
Set ("Nothing is fulfilled")
 
End If
Prnl
End
 
Output:
 
V, X and Y are true
 
 
Example #3:
 
Here only the macro "»" which means "CPY" (copy the memory value to the indicated variable but without removing it) allows to extend the use of "IF" (which is also a macro that extends the base language), according to the example:
 
#include <jambo.h>
 
Main
True(v), False(w), first option=0, second option=0
If ( var 'v' » 'first option', And ( w » 'second option' ) )
Printnl("Both options are true")
 
Else If ( first option )
Printnl("The first option is true")
 
Else If ( second option )
Printnl("The second option is true")
Else
Printnl ("None is true")
End If
End
 
Output:
 
The first option is true
</pre>
 
=={{header|Arturo}}==
<langsyntaxhighlight lang="rebol">if2: function [cond1 cond2 both one two none][
case []
when? [and? cond1 cond2] -> do both
Line 182 ⟶ 458:
[print "only first"]
[print "only second"]
[print "none"]</langsyntaxhighlight>
{{out}}
 
<pre>only second</pre>
 
=={{header|ATS}}==
 
See also [[#OCaml|OCaml]] and [[#Standard_ML|Standard ML]].
 
<syntaxhighlight lang="ats">(* Languages with pattern matching ALREADY HAVE THIS! *)
 
fn
func (pred1 : bool, pred2 : bool) : void =
case+ (pred1, pred2) of
| (true, true) => println! ("(true, true)")
| (true, false) => println! ("(true, false)")
| (false, true) => println! ("(false, true)")
| (false, false) => println! ("(false, false)")
 
implement
main0 () =
begin
func (true, true);
func (true, false);
func (false, true);
func (false, false)
end</syntaxhighlight>
{{out}}
<pre>$ patscc extend_your_language.dats && ./a.out
(true, true)
(true, false)
(false, true)
(false, false)</pre>
 
=={{header|C}}==
This task requires syntax different from the <code>if</code> keyword in C. For example:
 
<langsyntaxhighlight lang="c">/* Four-way branch.
*
* if2 (firsttest, secondtest
Line 207 ⟶ 512:
case 3: bothfalse; break;\
}
</syntaxhighlight>
</lang>
 
Example application:
 
<langsyntaxhighlight lang="c">#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
Line 234 ⟶ 539:
}
return 0;
}</langsyntaxhighlight>
 
Example invocation:
 
<langsyntaxhighlight lang="bash">$ make exten && ./exten 3 33 333 3a b " " -2
cc exten.c -o exten
3: a number
Line 246 ⟶ 551:
b: not a number
: not a number
-2: a number</langsyntaxhighlight>
 
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.
<langsyntaxhighlight lang="c">#include <stdio.h>
 
#define if2(a, b) switch(((a)) + ((b)) * 2) { case 3:
Line 282 ⟶ 587:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">
 
using System;
Line 414 ⟶ 719:
}
 
</syntaxhighlight>
</lang>
{{out| Program Output}}
<pre>
Line 433 ⟶ 738:
=={{header|Clay}}==
 
<langsyntaxhighlight lang="clay">alias if2(cond1:Bool,
cond2:Bool,
both,
Line 448 ⟶ 753:
return neither;
}
</syntaxhighlight>
</lang>
 
=={{header|Clojure}}==
Clojure being a LISP has macros.
 
<langsyntaxhighlight lang="clojure">
(defmacro if2 [[cond1 cond2] bothTrue firstTrue secondTrue else]
`(let [cond1# ~cond1
Line 459 ⟶ 764:
(if cond1# (if cond2# ~bothTrue ~firstTrue)
(if cond2# ~secondTrue ~else))))
</syntaxhighlight>
</lang>
 
<pre>
Line 474 ⟶ 779:
(if (quote c1) (if cond2__1806__auto__ (quote bothTrue) (quote firstTrue))
(if cond2__1806__auto__ (quote secondTrue) (quote else))))
</pre>
 
An alternative, cleaner way using case macro of Clojure:
<syntaxhighlight lang="clojure">
(defmacro if2
[cond1 cond2 both-true first-true second-true both-false]
`(case [~cond1 ~cond2]
[true true] ~both-true,
[true false] ~first-true,
[false true] ~second-true
[false false] ~both-false))
</syntaxhighlight>
 
<pre>
> (if2 true false \a \b \c \d)
\b
> (macroexpand-1 '(if2 true false \a \b \c \d))
(clojure.core/case [true false] [true true] \a [true false] \b [false true] \c [false false] \d)
</pre>
 
=={{header|COBOL}}==
Cobol already has a multiple-if:
<langsyntaxhighlight lang="cobol">
EVALUATE EXPRESSION-1 ALSO EXPRESSION-2
WHEN TRUE ALSO TRUE
Line 489 ⟶ 812:
DISPLAY 'Neither is true.'
END-EVALUATE
</syntaxhighlight>
</lang>
(Of course, Cobol is also inherently non-extensible.)
 
=={{header|Common Lisp}}==
 
<langsyntaxhighlight lang="lisp">(defmacro if2 (cond1 cond2 both first second &rest neither)
(let ((res1 (gensym))
(res2 (gensym)))
Line 502 ⟶ 825:
(,res1 ,first)
(,res2 ,second)
(t ,@neither)))))</langsyntaxhighlight>
 
Interactive tests to validate if2.
Line 556 ⟶ 879:
=={{header|Coq}}==
Coq allows "[https://coq.inria.fr/refman/user-extensions/syntax-extensions.html syntax extensions]":
<langsyntaxhighlight lang="coq">
Notation "A /\ B" := (and A B)
</syntaxhighlight>
</lang>
 
=={{header|D}}==
D features lazy arguments, which can be used for this task.
 
<langsyntaxhighlight lang="d">void if2(T1, T2, T3, T4)(in bool c1, in bool c2,
lazy T1 first,
lazy T2 both,
Line 594 ⟶ 917:
test(3 > 4, 3 > 4);
test(3 > 4, 1 < 2);
}</langsyntaxhighlight>
{{out}}
<pre>first
Line 605 ⟶ 928:
First example:
 
<langsyntaxhighlight lang="delphi">
procedure Check(Condition1: Boolean; Condition2: Boolean)
begin
Line 620 ⟶ 943:
else
NoConditionIsTrue;
end;</langsyntaxhighlight>
 
Second example:
 
<langsyntaxhighlight lang="delphi">
procedure Check(Condition1: Boolean; Condition2: Boolean)
begin
Line 634 ⟶ 957:
SecondConditionIsTrue
else NoConditionIsTrue;
end;</langsyntaxhighlight>
 
In both examples if Condition1 and/or Condition2 are Booleans you can omit the '= True' (not when for instance comparing Integers: a = 1)
Line 658 ⟶ 981:
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.
 
<langsyntaxhighlight lang="dup">{two-conditional if operator implementation}
{ [ top cond. = true ][ top cond. = false ]}
{ [ 2nd = true ][2nd = false ] [ 2nd = true ][ 2nd = false] }
[(((([[)))!)))%%%%%][)))))!)%%%%%]?][[))))!))%%%%%][))))))!%%%%%]?]?]⇒¿
</syntaxhighlight>
</lang>
 
Example program:
 
<langsyntaxhighlight lang="dup">0 1_['t,'t,]['t,'f,]['f,'t,]['f,'f,]¿</langsyntaxhighlight>
 
Resulting output of the example program:
Line 680 ⟶ 1,003:
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.
 
<langsyntaxhighlight lang="e">pragma.enable("lambda-args") # The feature is still experimental syntax
 
def makeIf2Control(evalFn, tf, ft, ff) {
Line 723 ⟶ 1,046:
}
}
}</langsyntaxhighlight>
 
The internal expansion of the "if2" block above is:
 
<langsyntaxhighlight lang="e">if2.then__control_2_0(fn {
[[a, b], fn {
println("both")
Line 737 ⟶ 1,060:
}).else__control_0(fn {
println("neither")
}).run__control()</langsyntaxhighlight>
 
=={{header|EchoLisp}}==
'''define-syntax''' and '''define-syntax-rules''' are here to extend the language
<langsyntaxhighlight lang="scheme">
(define-syntax-rule
(if2 cond1 cond2 both cond1-only cond2-only none) ;; new syntax
Line 766 ⟶ 1,089:
→ "positive and inexact"
 
</syntaxhighlight>
</lang>
 
=={{header|Emacs Lisp}}==
The same macro that works in Common Lisp will work in Emacs Lisp for this problem:
<langsyntaxhighlight lang="lisp">
(defmacro if2 (cond1 cond2 both first second &rest neither)
(let ((res1 (gensym))
Line 780 ⟶ 1,103:
(,res2 ,second)
(t ,@neither)))))
</syntaxhighlight>
</lang>
{{Out}}
Interactive tests to validate if2.
Line 815 ⟶ 1,138:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
// Extend your language. Nigel Galloway: September 14th., 2021
type elsetf=TF
Line 838 ⟶ 1,161:
elseft (fun()->printfn "ft")
elseff (fun()->printfn "ff")
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 847 ⟶ 1,170:
</pre>
Looking at some possible errors found by the compiler:
<langsyntaxhighlight lang="fsharp">
if2 (13<23) (23<42) (fun()->printfn "tt")
elseff (fun()->printfn "tf")
elseft (fun()->printfn "ft")
elseff (fun()->printfn "ff")
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 860 ⟶ 1,183:
'elseff'
</pre>
<langsyntaxhighlight lang="fsharp">
if2 (13<23) (42<23) (fun()->printfn "tt")
elsetx (fun()->printfn "tf")
elseft (fun()->printfn "ft")
elseff (fun()->printfn "ff")
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 875 ⟶ 1,198:
=={{header|Factor}}==
Not too hard, as long as you're not worried about choking to death on stack effects:
<langsyntaxhighlight 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
( scratchpad ) 3 [ 0 > ] [ even? ] bi [ 0 ] [ 1 ] [ 2 ] [ 3 ] 2ifte .
2</langsyntaxhighlight>
 
=={{header|Fennel}}==
<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.
(macro if2 [cond1 cond2 both first second none]
`(if ,cond1
(if ,cond2 ,both ,first)
(if ,cond2 ,second ,none)))
 
(fn test-if2 [x y]
(if2 x y
(print "both")
(print "first")
(print "second")
(print "none")))
 
(test-if2 true true) ;"both"
(test-if2 true false) ;"first"
(test-if2 false true) ;"second"
(test-if2 false false) ;"none"</syntaxhighlight>
 
=={{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.
<langsyntaxhighlight lang="forth">\ in this construct, either of the ELSE clauses may be omitted, just like IF-THEN.
 
: BOTH postpone IF postpone IF ; immediate
Line 896 ⟶ 1,239:
NEITHER drop ;
: fizzbuzz ( n -- ) 0 do i 1+ fb loop ;
</syntaxhighlight>
</lang>
 
=={{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.
 
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: <langsyntaxhighlight Fortranlang="fortran"> LOGICAL A,B !These are allocated the same storage
INTEGER IA,IB !As the default integer size.
EQUIVALENCE (IA,A),(IB,B) !So, this will cause no overlaps.
Line 951 ⟶ 1,294:
 
999 CONTINUE
END</langsyntaxhighlight>
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>
Line 972 ⟶ 1,315:
TT -1 -1 -3
</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: <langsyntaxhighlight Fortranlang="fortran"> INTEGER FUNCTION IF2(A,B) !Combine two LOGICAL variables.
LOGICAL A,B !These.
IF2 = 0 !Wasted effort if A is true.
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+)
END FUNCTION IF2 !Thus produce a four-way result.</langsyntaxhighlight>
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: <langsyntaxhighlight Fortranlang="fortran"> SELECT CASE(IF2(A,B))
CASE(B"00"); WRITE (6,*) "Both false."
CASE(B"01"); WRITE (6,*) "B only."
CASE(B"10"); WRITE (6,*) "A only."
CASE(B"11"); WRITE (6,*) "Both true."
END SELECT</langsyntaxhighlight>
 
But there is no extension to the allowed syntax, as such.
Line 993 ⟶ 1,336:
 
Note, as of 2019‑09‑04 this construct works only with a trunk FPC version.
<langsyntaxhighlight lang="pascal">program fourWay(input, output, stdErr);
var
tuple: record
Line 1,016 ⟶ 1,359:
end;
end;
end.</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' FB 1.05.0 Win64
 
#Macro If2(condition1, condition2)
Line 1,050 ⟶ 1,393:
Print
Print "Press any key to quit"
Sleep</langsyntaxhighlight>
 
{{out}}
Line 1,068 ⟶ 1,411:
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.
 
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 1,125 ⟶ 1,468:
fmt.Println("a = 1 and b <> 3")
})
}</langsyntaxhighlight>
 
{{out}}
Line 1,136 ⟶ 1,479:
Expressions in Haskell are not evaluated until they are needed, so ordinary functions can be control structures.
 
<langsyntaxhighlight lang="haskell">if2 :: Bool -> Bool -> a -> a -> a -> a -> a
if2 p1 p2 e12 e1 e2 e =
if p1 then
Line 1,143 ⟶ 1,486:
 
main = print $ if2 True False (error "TT") "TF" (error "FT") (error "FF")
</syntaxhighlight>
</lang>
 
=={{header|Icon}} and {{header|Unicon}}==
Line 1,151 ⟶ 1,494:
(PDCO) may be defined and used. Here is an example:
 
<langsyntaxhighlight lang="unicon">procedure main(A)
if2 { (A[1] = A[2]), (A[3] = A[4]), # Use PDCO with all three else clauses
write("1: both true"),
Line 1,170 ⟶ 1,513:
else if @A[2] then |@\A[5]
else |@\A[6]
end</langsyntaxhighlight>
 
and some sample runs:
Line 1,196 ⟶ 1,539:
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.
 
<langsyntaxhighlight lang="idris">if2 : Bool -> Bool -> Lazy a -> Lazy a -> Lazy a -> Lazy a -> a
if2 True True v _ _ _ = v
if2 True False _ v _ _ = v
if2 False True _ _ v _ = v
if2 _ _ _ _ _ v = v</langsyntaxhighlight>
 
=={{header|Inform 7}}==
Line 1,206 ⟶ 1,549:
=== 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:
<langsyntaxhighlight 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 else2 -- in if2: (- } until (1); 1: do { -).
To else0 -- in if2: (- } until (1); 0: -).</langsyntaxhighlight>
 
Note that the "else0" part must be given, although "else1" and "else2" are optional. Demonstration:
<langsyntaxhighlight lang="inform7">Home is a room.
 
When play begins:
Line 1,223 ⟶ 1,566:
else0;
say "neither";
end if2.</langsyntaxhighlight>
 
=== Text substitution ===
<langsyntaxhighlight lang="inform7">To say if2 (c1 - condition) and-or (c2 - condition) -- beginning if2:
(- switch (({c1})*2 + ({c2})) { 3: -).
To say else1 -- continuing if2: (- 2: -).
To say else2 -- continuing if2: (- 1: -).
To say else0 -- continuing if2: (- 0: -).
To say end if2 -- ending if2: (- } -).</langsyntaxhighlight>
 
Demonstration:
<langsyntaxhighlight lang="inform7">Home is a room.
 
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]".</langsyntaxhighlight>
 
=={{header|J}}==
Line 1,249 ⟶ 1,592:
Here, we extend our language by defining a conjunction <code>if2</code> which consumes two nouns and produces a verb:
 
<langsyntaxhighlight lang="j">if2=: 2 :0
'`b1 b2'=. n
m@.(b1 + 2 * b2) f.
)</langsyntaxhighlight>
 
Example use:
 
<langsyntaxhighlight lang="j">f0=: [: smoutput 'neither option: ' , ":
f1=: [: smoutput 'first option: ' , ":
f2=: [: smoutput 'second option: ' , ":
Line 1,269 ⟶ 1,612:
both options: 2
first option: 3
second option: 4</langsyntaxhighlight>
 
That said, note that a switch statement which combines the boolean conditions as a base 2 number might be more convenient.
Line 1,281 ⟶ 1,624:
Java lambdas can go a long way towards allowing the implementation of lazy "branches", as this example shows.
 
<langsyntaxhighlight lang="java">
public class If2 {
 
Line 1,295 ⟶ 1,638:
}
}
</syntaxhighlight>
</lang>
 
Usage:
 
<langsyntaxhighlight lang="java">
import static If2.if2;
class Main {
Line 1,315 ⟶ 1,658:
}
}
</syntaxhighlight>
</lang>
 
To allow optional else branches, and perhaps a more readable syntax with named branches, a more Object-Oriented approach can be used:
 
<langsyntaxhighlight lang="java">
public class If2 {
private final boolean firstCondition;
Line 1,361 ⟶ 1,704:
}
}
</syntaxhighlight>
</lang>
 
Usage (imports and main class ommited for brevity):
 
<langsyntaxhighlight lang="java">
// prints "both true"
if2(true, true)
Line 1,380 ⟶ 1,723:
print("none true");
});
</syntaxhighlight>
</lang>
 
=={{header|jq}}==
{{works with|jq}}
'''Works with gojq'''
 
'''With tweak, works with jaq'''
 
As is the case with C and some other languages with entries on this page, jq lacks the flexibility to meet the requirement that "The new conditional expression should look, nest and behave analogously to the language's built-in 'if' statement."
 
However, as with D, for example,
it is easy to define an `if3` that is semantically analogous to the built-in `if` statement because
function arguments can be evaluated lazily. Furthermore, in the case of jq, one can specify that
an argument should be evaluated eagerly, which turns out to be helpful in the present case as it makes short work of
avoiding the semantic error of double evaluation of conditionals that have side-effects.
 
Here, then, is a definition of `if3` that imposes no restrictions on its arguments in the same sense that the built-in `if` has none:
<syntaxhighlight lang=jq>
def if2($c1; $c2; both; first; second; neither):
if $c1 and $c2 then both
elif $c1 then first
elif $c2 then second
else neither
end;
</syntaxhighlight>
 
### jaq
Since jaq does not currently support $-variables in function headers,
the definition would have to be modified to:
<syntaxhighlight lang=jq>
def if2(c1; c2; both; first; second; neither):
c1 as $c1
| c2 as $c2
| if $c1 and $c2 then both
elif $c1 then first
elif $c2 then second
else neither
end;
</syntaxhighlight>
 
 
=={{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.
<langsyntaxhighlight lang="julia">
const CSTACK1 = Array{Bool,1}()
const CSTACK2 = Array{Bool,1}()
Line 1,476 ⟶ 1,858:
 
@elseifneither(begin println("neither") end)
</syntaxhighlight>
</lang>
{{output}}<pre>
all
Line 1,486 ⟶ 1,868:
=={{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:
<langsyntaxhighlight lang="scala">// version 1.0.6
 
data class IfBoth(val cond1: Boolean, val cond2: Boolean) {
Line 1,538 ⟶ 1,920:
println("a = 1 and b <> 3")
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,548 ⟶ 1,930:
=={{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)
<langsyntaxhighlight lang="lua">-- Extend your language, in Lua, 6/17/2020 db
-- not to be taken seriously, ridiculous, impractical, esoteric, obscure, arcane ... but it works
 
Line 1,588 ⟶ 1,970:
 
end
end</langsyntaxhighlight>
{{out}}
<pre>i=1 j=1
Line 1,603 ⟶ 1,985:
Lambdatalk comes with macros translating regular expressions into lambdatalk expressions
 
<syntaxhighlight lang="scheme">
<lang Scheme>
{macro \{if2 (true|false|\{[^{}]*\}) (true|false|\{[^{}]*\})\}
to {if {and $1 $2}
Line 1,622 ⟶ 2,004:
{if2 {> 1 2} {< 3 4}} -> the second is true
{if2 {> 1 2} {> 3 4}} -> neither are true
</syntaxhighlight>
</lang>
 
=={{header|langur}}==
Langur doesn't currently have macros, but the following will otherwise accomplish the task, using the fact that a givenswitch expression may accept multiple test expressions. No extension of the language is necessary. This is not limited to 2 conditions.
 
We could use the nxor (logical equivalence) operator to test truthiness.
 
<langsyntaxhighlight lang="langur">givenswitch[and] .x nxor, .y nxor {
case true: ... # both true
case true, false: ... # first true, second false
case false, true: ... # first false, second true
default: ... # both false
}</langsyntaxhighlight>
 
To test directly for Boolean values (not truthiness), we could use the default == comparison.
 
<langsyntaxhighlight lang="langur">givenswitch[and] .x, .y {
case true: ... # both true
case true, false: ... # first true, second false
case false, true: ... # first false, second true
case null, _: ... # first null, second irrelevant
default: ... # other
}</langsyntaxhighlight>
 
=={{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.
 
<langsyntaxhighlight Lassolang="lasso">// Create a type to handle the captures
 
define if2 => type {
Line 1,671 ⟶ 2,053:
define else1 => thread_var_get(::if2)->else1 => givenblock
define else2 => thread_var_get(::if2)->else2 => givenblock
define else => thread_var_get(::if2)->else => givenblock</langsyntaxhighlight>
 
Example use:
 
<langsyntaxhighlight Lassolang="lasso">if2(true,true) => {
ifboth => {
bothConditionsAreTrue
Line 1,688 ⟶ 2,070:
noConditionIsTrue
}
}</langsyntaxhighlight>
 
=={{header|M2000 Interpreter}}==
Line 1,709 ⟶ 2,091:
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 {
over 3 : read &c
Line 1,750 ⟶ 2,132:
Print "ok"
 
</syntaxhighlight>
</lang>
 
=={{header|m4}}==
 
<lang m4>divert(-1)
See also [[#Plain_TeX|Plain TeX]].
 
<syntaxhighlight lang="m4">divert(-1)
 
#
Line 1,773 ⟶ 2,158:
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')</langsyntaxhighlight>
 
{{out}}
Line 1,784 ⟶ 2,169:
=={{header|Mathematica}} / {{header|Wolfram Language}}==
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[
{result1 = test1,
Line 1,794 ⟶ 2,179:
True, condNone]];
SetAttributes[If2, HoldAll];
</syntaxhighlight>
</lang>
 
Example usage (note that the tests are evaluated only once per call):
<syntaxhighlight lang="mathematica">
<lang Mathematica>
x = 0;
If2[Mod[(++x), 2] == 0, Mod[x, 3] == 1, Print["Both: ", x], Print["First: ", x], Print["Second: ", x], Print["Neither: ", x]];
Line 1,803 ⟶ 2,188:
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}}
<pre>
Line 1,815 ⟶ 2,200:
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}}
<langsyntaxhighlight lang="min">(
:none :two :one :both -> :r2 -> :r1
(
Line 1,837 ⟶ 2,222:
("false")
if puts! ;true
</syntaxhighlight>
</lang>
 
=={{header|Morfa}}==
Morfa's operator defining and overloading can be employed to provide more natural syntax for expressing an <tt>if2</tt> "statement".
<langsyntaxhighlight lang="morfa">
import morfa.base;
 
Line 1,919 ⟶ 2,304:
println("none true");
};
</syntaxhighlight>
</lang>
 
=={{header|Nemerle}}==
In file "if2macro.n":
<syntaxhighlight lang="nemerle">
<lang Nemerle>
// point of interest: the when keyword and && operator inside the macro definition are macros themselves
 
Line 1,935 ⟶ 2,320:
when(!($cond1) && !($cond2)) {$bodyFF};
]>
}</langsyntaxhighlight>
Compile with:
<pre> ncc -r Nemerle.Compiler.dll -t:dll if2macro.n -o if2macro.dll</pre>
In file useif2.n:
<langsyntaxhighlight Nemerlelang="nemerle">using System;
using System.Console;
 
Line 1,958 ⟶ 2,343:
Write("You're unhappy, cheer up");
}
}</langsyntaxhighlight>
Compile with:<pre>ncc -r if2macro.dll useif2.n</pre>
 
=={{header|NewLISP}}==
 
<langsyntaxhighlight NewLISPlang="newlisp">(context 'if2)
 
(define-macro (if2:if2 cond1 cond2 both-true first-true second-true neither)
Line 1,986 ⟶ 2,371:
> (if2 false false 'bothTrue 'firstTrue 'secondTrue 'else)
else
</syntaxhighlight>
</lang>
 
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">import macros
proc newIfElse(c, t, e: NimNode): NimNode {.compiletime.} =
Line 2,050 ⟶ 2,435:
echo "2"
else3:
echo "4"</langsyntaxhighlight>
 
=={{header|OCaml}}==
 
In OCaml you can extend the language as proposed by ... thinking outside the box.
 
See also [[#ATS|ATS]] and [[#Standard_ML|Standard ML]].
 
Of course, OCaml has a history of people devising entirely different syntaxes for the language, using a preprocessor. So that could be done. However, pattern matchers already support endless varieties of branching.
 
The same goes for pattern matchers in Lisps, such as the widely used public domain pattern matcher for Scheme.
 
<syntaxhighlight lang="ocaml">(* Languages with pattern matching ALREADY HAVE THIS! *)
 
let myfunc pred1 pred2 =
match (pred1, pred2) with
| (true, true) -> print_endline ("(true, true)");
| (true, false) -> print_endline ("(true, false)");
| (false, true) -> print_endline ("(false, true)");
| (false, false) -> print_endline ("(false, false)");;
 
myfunc true true;;
myfunc true false;;
myfunc false true;;
myfunc false false;;</syntaxhighlight>
 
{{out}}
<pre>$ ocaml extend_your_language-ocaml.ml
(true, true)
(true, false)
(false, true)
(false, false)</pre>
 
=={{header|PARI/GP}}==
Of course the language can be extended with GP functions (starting with version 2.4.2, these are closures).
<langsyntaxhighlight lang="parigp">if2(c1,c2,tt,tf,ft,ff)={
if(c1,
if(c2,tt,tf)
Line 2,060 ⟶ 2,476:
if(c2,ft,ff)
)
};</langsyntaxhighlight>
 
GP can also be extended by adding C code directly to Pari:
<langsyntaxhighlight Clang="c">GEN
if2(GEN c1, GEN c2, GEN tt, GEN tf, GEN ft, GEN ff)
{
Line 2,076 ⟶ 2,492:
else
return tt ? closure_evalgen(tt) : gnil;
}</langsyntaxhighlight>
 
This function, when compiled to the file <code>if2.gp.so</code>, can be loaded into GP with the following commands:
<langsyntaxhighlight 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.");</langsyntaxhighlight>
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;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.");
*/</langsyntaxhighlight>
 
=={{header|Perl}}==
Line 2,091 ⟶ 2,507:
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.
 
<langsyntaxhighlight lang="perl">
#!/usr/bin/perl
use warnings;
Line 2,226 ⟶ 2,642:
 
test_bits $_ for 0 .. 7;
</syntaxhighlight>
</lang>
 
Sample run:
 
<syntaxhighlight lang="text">
msl@64Lucid:~/perl$ ./if2
Testing 0: Neither bit is set
Line 2,241 ⟶ 2,657:
Testing 7: Both bits 0 and 1 are set
msl@64Lucid:~/perl$
</syntaxhighlight>
</lang>
 
=={{header|Phix}}==
Phix does not support macro programming. Generally I would suggest one of the following
<!--<langsyntaxhighlight Phixlang="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;">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,252 ⟶ 2,668:
<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>
<!--</langsyntaxhighlight>-->
or
<!--<langsyntaxhighlight Phixlang="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;">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,265 ⟶ 2,681:
<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>
<!--</langsyntaxhighlight>-->
or
<!--<langsyntaxhighlight Phixlang="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>
Line 2,280 ⟶ 2,696:
<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>
<!--</langsyntaxhighlight>-->
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,313 ⟶ 2,729:
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)
<!--<langsyntaxhighlight Phixlang="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_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>
<!--</langsyntaxhighlight>-->
Then run p p and it will tell you what they should be
<pre>
Line 2,325 ⟶ 2,741:
</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):
<!--<langsyntaxhighlight Phixlang="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: #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>
<!--</langsyntaxhighlight>-->
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
Line 2,334 ⟶ 2,750:
 
Lastly, that would need to be hooked in, find the DoSwitch call (again in pmain.e) and insert after it:
<!--<langsyntaxhighlight Phixlang="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>
<!--</langsyntaxhighlight>-->
 
Recompile Phix (p -cp, approx 10s) and test.
Obviously, while I have subsequently removed it, I have tried this myself and it worked fine:
<!--<langsyntaxhighlight Phixlang="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: #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,353 ⟶ 2,769:
<span style="color: #008080;">end</span> <span style="color: #000000;">if2</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</langsyntaxhighlight>-->
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}}
Line 2,371 ⟶ 2,787:
 
=={{header|PHL}}==
<langsyntaxhighlight lang="phl">module stmts;
 
import phl::lang::io;
Line 2,423 ⟶ 2,839:
println("Not this!");
];
]</langsyntaxhighlight>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(undef 'if2) # Undefine the built-in 'if2'
 
(de if2 "P"
Line 2,433 ⟶ 2,849:
(if (eval (car "P"))
(eval (cadddr "P"))
(run (cddddr "P")) ) ) )</langsyntaxhighlight>
Usage:
<pre>(if2 (condition1isTrue) (condition2isTrue)
Line 2,449 ⟶ 2,865:
See also [[#m4|m4]].
 
<langsyntaxhighlight plainTeXlang="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}
 
Line 2,461 ⟶ 2,877:
\message{\iftwo{1}{-1}{2}{-2}\both\elsefirst\first\elsesecond\second\elseneither\neither\owtfi}
 
\bye</langsyntaxhighlight>
{{out}}
<pre>$ tex extend_your_language.tex
Line 2,470 ⟶ 2,886:
 
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function When-Condition
{
Line 2,518 ⟶ 2,934:
}
}
</syntaxhighlight>
</lang>
Full syntax:
<syntaxhighlight lang="powershell">
<lang PowerShell>
When-Condition -Test1 (Test-Path .\temp.txt) -Test2 (Test-Path .\tmp.txt) `
-Both { "both true"
Line 2,527 ⟶ 2,943:
} -Neither { "neither true"
}
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,533 ⟶ 2,949:
</pre>
Alternate syntax:
<syntaxhighlight lang="powershell">
<lang PowerShell>
Set-Alias -Name if2 -Value When-Condition
 
Line 2,542 ⟶ 2,958:
} { "neither true"
}
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,559 ⟶ 2,975:
Note, however, that this is not a syntax extension. The following example is included merely for the sake of completeness.
 
<langsyntaxhighlight lang="python">a, b = 1, 0
 
if (c1 := a == 1) and (c2 := b == 3):
Line 2,568 ⟶ 2,984:
print('a <> 1 and b = 3')
else:
print('a <> 1 and b <> 3')</langsyntaxhighlight>
 
=={{header|Quackery}}==
Line 2,574 ⟶ 2,990:
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.
 
<langsyntaxhighlight Quackerylang="quackery">( --------------------- version #1 --------------------- )
 
[ not swap not 1 << |
Line 2,610 ⟶ 3,026:
false true task.2
false false task.2
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,627 ⟶ 3,043:
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)
{
Line 2,636 ⟶ 3,052:
eval(expr)
}
</syntaxhighlight>
</lang>
 
A test example:
<syntaxhighlight lang="r">
<lang r>
for(x in 1:2) for(y in letters[1:2])
{
Line 2,652 ⟶ 3,068:
))
}
</syntaxhighlight>
</lang>
 
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)
{
Line 2,666 ⟶ 3,082:
eval(cl[[cl_name]])
}
</syntaxhighlight>
</lang>
 
The usage here is modified to
<syntaxhighlight lang="r">
<lang r>
for(x in 1:2) for(y in letters[1:2])
{
Line 2,683 ⟶ 3,099:
)))
}
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
Line 2,689 ⟶ 3,105:
Racket, like other Schemes, makes this kind of thing almost trivial:
 
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
;; define a new syntax
Line 2,718 ⟶ 3,134:
(try 10 1) ; Second 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:
Line 2,783 ⟶ 3,199:
 
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.)
<syntaxhighlight lang="raku" perl6line>my &if2 = -> \a, \b, &x { my @*IF2 = ?a,?b; x }
 
my &if-both = -> &x { x if @*IF2 eq (True,True) }
Line 2,803 ⟶ 3,219:
}
 
say test |$_ for 1,0 X 1,0;</langsyntaxhighlight>
{{out}}
<pre>Got both
Line 2,817 ⟶ 3,233:
 
'''Usage example:'''
<langsyntaxhighlight lang="rexx">if2( some-expression-that-results-in-a-boolean-value, some-other-expression-that-results-in-a-boolean-value)
 
 
Line 2,832 ⟶ 3,248:
/*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</langsyntaxhighlight>
<langsyntaxhighlight 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*/
if bot=='' | bot=="," then bot=10 /*Not specified? Then use the default.*/
Line 2,855 ⟶ 3,271:
if.11= if.10 & if.01 /* " " case " 11 */
if.00= \(if.10 | if.01) /* " " " " 00 */
return ''</langsyntaxhighlight>
'''output'''
<pre>
Line 2,877 ⟶ 3,293:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Extend your language
 
Line 2,901 ⟶ 3,317:
ok
see nl
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,908 ⟶ 3,324:
a = 0, b = 1 => second positive
a = 0, b = 0 => neither positive
</pre>
 
=={{header|RPL}}==
{{works with|Halcyon Calc|4.2.7}}
In RPL, the IFTE function returns either the first or the second level of the stack, depending on whether the third level is false or true respectively. The extension of this concept to the one proposed by the task is quite simple, and allows a true quadruple branching, as shown in the demonstration.
≪ 4 ROLL SWAP 4 ROLLD 4 →LIST
SWAP SIGN 2 * ROT SIGN + 1 + GET ≫
‘IF2TE’ STO
 
1 1 "Both" "First" "Second" "None" IF2TE
0 1 "Both" "First" "Second" "None" IF2TE
{{out}}
<pre>
2: "Both"
1: "Second"
</pre>
===Quadruple branching example===
≪ → hour min
≪ min 30 MOD min 30 <
≪ min →STR " PAST " + hour →STR + ≫
≪ 60 min - →STR " TO " + hour 1 + →STR + ≫
≪ hour →STR " PRECISELY" + ≫
≪ "HALF PAST " hour →STR + ≫
IF2TE EVAL
'SAYTIME' STO
 
3 25 SAYTIME
1 55 SAYTIME
6 30 SAYTIME
7 0 SAYTIME
{{out}}
<pre>
4: "25 PAST 3"
3: "5 TO 2"
2: "HALF PAST 6"
1: "7 PRECISELY"
</pre>
 
=={{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:
<langsyntaxhighlight lang="ruby"># Define a class which always returns itself for everything
class HopelesslyEgocentric
def method_missing(what, *args) self end
Line 2,934 ⟶ 3,388:
end.new
end
end</langsyntaxhighlight>
Usage:
<langsyntaxhighlight lang="ruby">[true,false].product([true,false]).each do |cond1, cond2|
print "%5s, %5s => " % [cond1, cond2]
if2(cond1, cond2) do
Line 2,947 ⟶ 3,401:
puts "neither is true"
end
end</langsyntaxhighlight>
{{out}}
<pre>
Line 2,957 ⟶ 3,411:
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">#![allow(unused_variables)]
macro_rules! if2 {
($cond1: expr, $cond2: expr
Line 2,987 ⟶ 3,441:
=> println!("neither were true")
)
}</langsyntaxhighlight>
 
=={{header|Scala}}==
 
Defining a new control construct:
<langsyntaxhighlight lang="scala">scala> def if2[A](x: => Boolean)(y: => Boolean)(xyt: => A) = new {
| def else1(xt: => A) = new {
| def else2(yt: => A) = new {
Line 3,008 ⟶ 3,462:
| }
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}}}</langsyntaxhighlight>
 
Usage:
<langsyntaxhighlight lang="scala">scala> if2(true)(true) {
| 1
| } else1 {
Line 3,031 ⟶ 3,485:
| "Zoro"
| }
res1: java.lang.String = Sanji</langsyntaxhighlight>
 
=={{header|Scheme}}==
<langsyntaxhighlight lang="scheme">
(define-syntax if2
(syntax-rules ()
Line 3,042 ⟶ 3,496:
(if c2 both-true first-true)
(if c2 second-true none-true))))))
</syntaxhighlight>
</lang>
 
=={{header|Seed7}}==
Seed7 allows the definition of statement [http://seed7.sourceforge.net/manual/syntax.htm syntax] and semantic.
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
$ syntax expr: .if.().().then.().else1.().else2.().else3.().end.if is -> 25;
Line 3,084 ⟶ 3,538:
writeln("error FALSE FALSE");
end if;
end func;</langsyntaxhighlight>
 
=={{header|Shen}}==
Like most Lisps, this is trivial in Shen.
<langsyntaxhighlight lang="shen">(defmacro branch-if-macro
[branch-if Cond1 Cond2 Both Fst Snd None] ->
[if Cond1
[if Cond2 Both Fst]
[if Cond2 Snd None]])</langsyntaxhighlight>
Example:
<langsyntaxhighlight lang="shen">
(define try
X Y -> (branch-if (integer? X)
Line 3,101 ⟶ 3,555:
 
(map (/. X (do (print X) (nl)))
[(try 1 2) (try 1 1.5) (try 1.5 1) (try 1.5 1.5)])</langsyntaxhighlight>
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">class if2(cond1, cond2) {
method then(block) { # both true
if (cond1 && cond2) {
Line 3,139 ⟶ 3,593:
}.else {
say "else"
}</langsyntaxhighlight>
=={{header|Smalltalk}}==
True method:&sup1; &sup2;
<langsyntaxhighlight lang="smalltalk">or:condition2 ifBoth:bothBlk ifFirst:firstBlk ifSecond:scndBlk ifNone:noneBlk
"I know for sure, that I am true..."
^ condition2 ifTrue:bothBlk ifFalse:firstBlk</langsyntaxhighlight>
False method:
<langsyntaxhighlight lang="smalltalk">or:condition2 ifBoth:bothBlk ifFirst:firstBlk ifSecond:scndBlk ifNone:noneBlk
"I know for sure, that I am false..."
^ condition2 ifTrue:scndBlk ifFalse:noneBlk</langsyntaxhighlight>
 
You can now write:
<langsyntaxhighlight lang="smalltalk">(a > 0) or:(b > 10)
ifBoth:[ 'both' printCR]
ifFirst:[ 'only first' printCR ]
ifSecond:[ 'only second' printCR ]
ifNone: [ 'none' printCR ]</langsyntaxhighlight>
 
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,161 ⟶ 3,615:
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):
<langsyntaxhighlight lang="smalltalk">If2 class method:
when:cond1 or:cond2 ifBoth:both ifFirst:first ifSecond:scnd ifNone:none
^ cond1 ifTrue:[
Line 3,167 ⟶ 3,621:
] ifFalse:[
cond2 ifTrue:scnd ifFalse:none
]</langsyntaxhighlight>
Now, you can write:
<langsyntaxhighlight lang="smalltalk">If2 when:(a > 0) or:(b > 10)
ifBoth:[ 'both' printCR]
ifFirst:[ 'only first' printCR ]
ifSecond:[ 'only second' printCR ]
ifNone: [ 'none' printCR ]</langsyntaxhighlight>
 
=={{header|Standard ML}}==
 
See also [[#ATS|ATS]] and [[#OCaml|OCaml]].
 
<syntaxhighlight lang="sml">(* Languages with pattern matching ALREADY HAVE THIS! *)
 
fun myfunc (pred1, pred2) =
case (pred1, pred2) of
(true, true) => print ("(true, true)\n")
| (true, false) => print ("(true, false)\n")
| (false, true) => print ("(false, true)\n")
| (false, false) => print ("(false, false)\n");
 
myfunc (true, true);
myfunc (true, false);
myfunc (false, true);
myfunc (false, false);</syntaxhighlight>
 
{{out}}
<pre>$ mlton extend_your_language.sml && ./extend_your_language
(true, true)
(true, false)
(false, true)
(false, false)</pre>
 
=={{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):
<langsyntaxhighlight lang="tcl">proc if2 {cond1 cond2 bothTrueBody firstTrueBody secondTrueBody bothFalseBody} {
# Must evaluate both conditions, and should do so in order
set c1 [uplevel 1 [list expr $cond1]
Line 3,191 ⟶ 3,670:
uplevel 1 $bothFalseBody
}
}</langsyntaxhighlight>
Demonstrating:
<langsyntaxhighlight lang="tcl">if2 {1 > 0} {"grill" in {foo bar boo}} {
puts "1 and 2"
} {
Line 3,201 ⟶ 3,680:
} {
puts "neither 1 nor 2"
}</langsyntaxhighlight>
Which produces this output:
<pre>1 but not 2</pre>
=== 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:
<langsyntaxhighlight lang="tcl">proc if2 {cond1 cond2 body00 body01 body10 body11} {
# Must evaluate both conditions, and should do so in order
# Extra negations ensure boolean interpretation
Line 3,213 ⟶ 3,692:
# Use those values to pick the script to evaluate
uplevel 1 [set body$c1$c2]
}</langsyntaxhighlight>
This behaves exactly as above, so shall not be repeated here.
=== Other language extension forms ===
Tcl includes very strong support for language extension. For example, consider this code which implements a integer looping command:
<langsyntaxhighlight lang="tcl">proc loop {varName lowerBound upperBound body} {
upvar 1 $varName var
for {set var $lowerBound} {$var <= $upperBound} {incr var} {
uplevel 1 $body
}
}</langsyntaxhighlight>
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:
<langsyntaxhighlight lang="tcl">proc timestables {M N} {
loop i 1 $M {
loop j 1 $N {
Line 3,231 ⟶ 3,710:
}
}
timestables 3 3</langsyntaxhighlight>
Output:
<pre>
Line 3,249 ⟶ 3,728:
{{trans|CommonLisp}}
 
<langsyntaxhighlight lang="txrlisp">(defmacro if2 (cond1 cond2 both first second . neither)
(let ((res1 (gensym))
(res2 (gensym)))
Line 3,257 ⟶ 3,736:
(,res1 ,first)
(,res2 ,second)
(t ,*neither)))))</langsyntaxhighlight>
 
=={{header|UNIX Shell}}==
Line 3,263 ⟶ 3,742:
 
{{works with|Bourne Shell}}
<langsyntaxhighlight lang="bash">if2() {
if eval "$1"; then
if eval "$2"; then eval "$3"; else eval "$4"; fi
Line 3,269 ⟶ 3,748:
if eval "$2"; then eval "$5"; else eval "$6"; fi
fi
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="bash">if2 'test 7 -lt 9' 'test 7 -gt 9' '
echo both 1 and 2
' '
Line 3,279 ⟶ 3,758:
' '
echo neither 1 nor 2
'</langsyntaxhighlight>
 
==={{header|es}}===
{{trans|Tcl}}
<langsyntaxhighlight lang="es">fn if2 cond1 cond2 body11 body10 body01 body00 {
# Must evaluate both conditions, and should do so in order.
# Negation ensures a boolean result: a true condition becomes
Line 3,291 ⟶ 3,770:
$(body$c1$c2)
}
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="es">if2 {test 1 -gt 0} {~ grill foo bar boo} {
echo 1 and 2
} {
Line 3,301 ⟶ 3,780:
} {
echo neither 1 nor 2
}</langsyntaxhighlight>
 
=={{header|Ursala}}==
Identifiers can't contain digits, so the function is named <code>iftwo</code>.
<langsyntaxhighlight Ursalalang="ursala">iftwo("p","q") <"both","justp","justq","neither"> =
 
"p"?(
"q"?("both","justp"),
"q"?("justq","neither"))</langsyntaxhighlight>
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
Line 3,321 ⟶ 3,800:
{{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.
<langsyntaxhighlight ecmascriptlang="wren">class IfBoth {
construct new(cond1, cond2) {
_cond1 = cond1
Line 3,372 ⟶ 3,851:
}.elseFirst {
System.print("a == 1 and b <> 3")
}</langsyntaxhighlight>
 
{{out}}
Line 3,382 ⟶ 3,861:
=={{header|XBS}}==
In XBS you are allowed to define custom syntax. The only real purpose for this is quick development or testing.
<langsyntaxhighlight lang="xbs">#>
newsyntax
@in:CH
Line 3,466 ⟶ 3,945:
equalsOneOrTwo(2);
equalsOneOrTwo(3);
equalsOneOrTwo(0);</langsyntaxhighlight>
{{out}}
<pre>
Line 3,477 ⟶ 3,956:
=={{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.
<langsyntaxhighlight lang="z80">cp b
jr nz,B_False
cp c
Line 3,503 ⟶ 3,982:
 
done:
;rest of program</langsyntaxhighlight>
 
 
Line 3,509 ⟶ 3,988:
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.
 
<langsyntaxhighlight 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
30 LET a=(x/2)=INT (x/2): REM comparison 1
Line 3,518 ⟶ 3,997:
80 PRINT x;" is divisible by 3": GO TO 100
90 PRINT x;" is divisible by 2 and 3"
100 NEXT x</langsyntaxhighlight>
{{out}}
<pre>1 is not divisible by 2 or 3
Line 3,548 ⟶ 4,027:
{{omit from|Commodore BASIC}}
{{omit from|Integer BASIC}}
{{omit from|Java}}
{{omit from|Lily}}
{{omit from|NetRexx}}
Line 3,556 ⟶ 4,034:
{{omit from|Yorick}}
{{omit from|zkl}}
{{omit from|Insitux}}
885

edits