Extend your language: Difference between revisions

m
syntax highlighting fixup automation
m (syntax highlighting fixup automation)
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}}==
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.
 
<langsyntaxhighlight 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)
Line 101:
move.b #1,d0
\@done:
endm</langsyntaxhighlight>
=={{header|Ada}}==
 
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO; use Ada.Text_IO;
 
procedure Test_If_2 is
Line 123:
end case;
end loop;
end Test_If_2;</langsyntaxhighlight>
 
{{out}}
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.
 
<langsyntaxhighlight lang="agda">
 
data Bool : Set where
Line 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 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 203:
)
end
end.</langsyntaxhighlight>
 
=={{header|Arturo}}==
<langsyntaxhighlight lang="rebol">if2: function [cond1 cond2 both one two none][
case []
when? [and? cond1 cond2] -> do both
Line 217:
[print "only first"]
[print "only second"]
[print "none"]</langsyntaxhighlight>
{{out}}
Line 227:
See also [[#OCaml|OCaml]] and [[#Standard_ML|Standard ML]].
 
<langsyntaxhighlight ATSlang="ats">(* Languages with pattern matching ALREADY HAVE THIS! *)
 
fn
Line 244:
func (false, true);
func (false, false)
end</langsyntaxhighlight>
{{out}}
<pre>$ patscc extend_your_language.dats && ./a.out
Line 255:
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 271:
case 3: bothfalse; break;\
}
</syntaxhighlight>
</lang>
 
Example application:
 
<langsyntaxhighlight lang="c">#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
Line 298:
}
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 310:
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 346:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">
 
using System;
Line 478:
}
 
</syntaxhighlight>
</lang>
{{out| Program Output}}
<pre>
Line 497:
=={{header|Clay}}==
 
<langsyntaxhighlight lang="clay">alias if2(cond1:Bool,
cond2:Bool,
both,
Line 512:
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 523:
(if cond1# (if cond2# ~bothTrue ~firstTrue)
(if cond2# ~secondTrue ~else))))
</syntaxhighlight>
</lang>
 
<pre>
Line 541:
 
An alternative, cleaner way using case macro of Clojure:
<langsyntaxhighlight lang="clojure">
(defmacro if2
[cond1 cond2 both-true first-true second-true both-false]
Line 549:
[false true] ~second-true
[false false] ~both-false))
</syntaxhighlight>
</lang>
 
<pre>
Line 560:
=={{header|COBOL}}==
Cobol already has a multiple-if:
<langsyntaxhighlight lang="cobol">
EVALUATE EXPRESSION-1 ALSO EXPRESSION-2
WHEN TRUE ALSO TRUE
Line 571:
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 584:
(,res1 ,first)
(,res2 ,second)
(t ,@neither)))))</langsyntaxhighlight>
 
Interactive tests to validate if2.
Line 638:
=={{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 676:
test(3 > 4, 3 > 4);
test(3 > 4, 1 < 2);
}</langsyntaxhighlight>
{{out}}
<pre>first
Line 687:
First example:
 
<langsyntaxhighlight lang="delphi">
procedure Check(Condition1: Boolean; Condition2: Boolean)
begin
Line 702:
else
NoConditionIsTrue;
end;</langsyntaxhighlight>
 
Second example:
 
<langsyntaxhighlight lang="delphi">
procedure Check(Condition1: Boolean; Condition2: Boolean)
begin
Line 716:
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 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.
 
<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 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.
 
<langsyntaxhighlight lang="e">pragma.enable("lambda-args") # The feature is still experimental syntax
 
def makeIf2Control(evalFn, tf, ft, ff) {
Line 805:
}
}
}</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 819:
}).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 848:
→ "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 862:
(,res2 ,second)
(t ,@neither)))))
</syntaxhighlight>
</lang>
{{Out}}
Interactive tests to validate if2.
Line 897:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
// Extend your language. Nigel Galloway: September 14th., 2021
type elsetf=TF
Line 920:
elseft (fun()->printfn "ft")
elseff (fun()->printfn "ff")
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 929:
</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 942:
'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 957:
=={{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}}==
<langsyntaxhighlight 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]
Line 980:
(test-if2 true false) ;"first"
(test-if2 false true) ;"second"
(test-if2 false false) ;"none"</langsyntaxhighlight>
 
=={{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 998:
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 1,053:
 
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 1,074:
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 1,095:
 
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,118:
end;
end;
end.</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">' FB 1.05.0 Win64
 
#Macro If2(condition1, condition2)
Line 1,152:
Print
Print "Press any key to quit"
Sleep</langsyntaxhighlight>
 
{{out}}
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.
 
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 1,227:
fmt.Println("a = 1 and b <> 3")
})
}</langsyntaxhighlight>
 
{{out}}
Line 1,238:
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,245:
 
main = print $ if2 True False (error "TT") "TF" (error "FT") (error "FF")
</syntaxhighlight>
</lang>
 
=={{header|Icon}} and {{header|Unicon}}==
Line 1,253:
(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,272:
else if @A[2] then |@\A[5]
else |@\A[6]
end</langsyntaxhighlight>
 
and some sample runs:
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.
 
<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,308:
=== 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,325:
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,351:
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,371:
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,383:
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,397:
}
}
</syntaxhighlight>
</lang>
 
Usage:
 
<langsyntaxhighlight lang="java">
import static If2.if2;
class Main {
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:
 
<langsyntaxhighlight lang="java">
public class If2 {
private final boolean firstCondition;
Line 1,463:
}
}
</syntaxhighlight>
</lang>
 
Usage (imports and main class ommited for brevity):
 
<langsyntaxhighlight lang="java">
// prints "both true"
if2(true, true)
Line 1,482:
print("none true");
});
</syntaxhighlight>
</lang>
 
=={{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,578:
 
@elseifneither(begin println("neither") end)
</syntaxhighlight>
</lang>
{{output}}<pre>
all
Line 1,588:
=={{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,640:
println("a = 1 and b <> 3")
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,650:
=={{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,690:
 
end
end</langsyntaxhighlight>
{{out}}
<pre>i=1 j=1
Line 1,705:
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,724:
{if2 {> 1 2} {< 3 4}} -> the second is true
{if2 {> 1 2} {> 3 4}} -> neither are true
</syntaxhighlight>
</lang>
 
=={{header|langur}}==
Line 1,731:
We could use the nxor (logical equivalence) operator to test truthiness.
 
<langsyntaxhighlight lang="langur">given .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">given .x, .y {
case true: ... # both true
case true, false: ... # first true, second false
Line 1,746:
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,773:
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,790:
noConditionIsTrue
}
}</langsyntaxhighlight>
 
=={{header|M2000 Interpreter}}==
Line 1,811:
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,852:
Print "ok"
 
</syntaxhighlight>
</lang>
 
=={{header|m4}}==
Line 1,858:
See also [[#Plain_TeX|Plain TeX]].
 
<langsyntaxhighlight lang="m4">divert(-1)
 
#
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')</langsyntaxhighlight>
 
{{out}}
Line 1,889:
=={{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,899:
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,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]];
</syntaxhighlight>
</lang>
{{out}}
<pre>
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.
{{works with|min|0.27.1}}
<langsyntaxhighlight lang="min">(
:none :two :one :both -> :r2 -> :r1
(
Line 1,942:
("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 2,024:
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 2,040:
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 2,063:
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 2,091:
> (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,155:
echo "2"
else3:
echo "4"</langsyntaxhighlight>
 
=={{header|OCaml}}==
Line 2,167:
The same goes for pattern matchers in Lisps, such as the widely used public domain pattern matcher for Scheme.
 
<langsyntaxhighlight lang="ocaml">(* Languages with pattern matching ALREADY HAVE THIS! *)
 
let myfunc pred1 pred2 =
Line 2,179:
myfunc true false;;
myfunc false true;;
myfunc false false;;</langsyntaxhighlight>
 
{{out}}
Line 2,190:
=={{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,196:
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,212:
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,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.
 
<langsyntaxhighlight lang="perl">
#!/usr/bin/perl
use warnings;
Line 2,362:
 
test_bits $_ for 0 .. 7;
</syntaxhighlight>
</lang>
 
Sample run:
 
<syntaxhighlight lang="text">
msl@64Lucid:~/perl$ ./if2
Testing 0: Neither bit is set
Line 2,377:
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,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;">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,401:
<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,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;">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,449:
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,461:
</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,470:
 
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,489:
<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,507:
 
=={{header|PHL}}==
<langsyntaxhighlight lang="phl">module stmts;
 
import phl::lang::io;
Line 2,559:
println("Not this!");
];
]</langsyntaxhighlight>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(undef 'if2) # Undefine the built-in 'if2'
 
(de if2 "P"
Line 2,569:
(if (eval (car "P"))
(eval (cadddr "P"))
(run (cddddr "P")) ) ) )</langsyntaxhighlight>
Usage:
<pre>(if2 (condition1isTrue) (condition2isTrue)
Line 2,585:
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,597:
\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,606:
 
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function When-Condition
{
Line 2,654:
}
}
</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,663:
} -Neither { "neither true"
}
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,669:
</pre>
Alternate syntax:
<syntaxhighlight lang="powershell">
<lang PowerShell>
Set-Alias -Name if2 -Value When-Condition
 
Line 2,678:
} { "neither true"
}
</syntaxhighlight>
</lang>
{{Out}}
<pre>
Line 2,695:
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,704:
print('a <> 1 and b = 3')
else:
print('a <> 1 and b <> 3')</langsyntaxhighlight>
 
=={{header|Quackery}}==
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.
 
<langsyntaxhighlight Quackerylang="quackery">( --------------------- version #1 --------------------- )
 
[ not swap not 1 << |
Line 2,746:
false true task.2
false false task.2
</syntaxhighlight>
</lang>
 
{{out}}
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.)
 
<syntaxhighlight lang="r">
<lang r>
if2 <- function(condition1, condition2, both_true, first_true, second_true, both_false)
{
Line 2,772:
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,788:
))
}
</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,802:
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,819:
)))
}
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
Line 2,825:
Racket, like other Schemes, makes this kind of thing almost trivial:
 
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
;; define a new syntax
Line 2,854:
(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,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.)
<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,939:
}
 
say test |$_ for 1,0 X 1,0;</langsyntaxhighlight>
{{out}}
<pre>Got both
Line 2,953:
 
'''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,968:
/*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,991:
if.11= if.10 & if.01 /* " " case " 11 */
if.00= \(if.10 | if.01) /* " " " " 00 */
return ''</langsyntaxhighlight>
'''output'''
<pre>
Line 3,013:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Extend your language
 
Line 3,037:
ok
see nl
</syntaxhighlight>
</lang>
Output:
<pre>
Line 3,048:
=={{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 3,070:
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 3,083:
puts "neither is true"
end
end</langsyntaxhighlight>
{{out}}
<pre>
Line 3,093:
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">#![allow(unused_variables)]
macro_rules! if2 {
($cond1: expr, $cond2: expr
Line 3,123:
=> 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,144:
| }
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,167:
| "Zoro"
| }
res1: java.lang.String = Sanji</langsyntaxhighlight>
 
=={{header|Scheme}}==
<langsyntaxhighlight lang="scheme">
(define-syntax if2
(syntax-rules ()
Line 3,178:
(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,220:
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,237:
 
(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,275:
}.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,297:
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,303:
] 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}}==
Line 3,315:
See also [[#ATS|ATS]] and [[#OCaml|OCaml]].
 
<langsyntaxhighlight lang="sml">(* Languages with pattern matching ALREADY HAVE THIS! *)
 
fun myfunc (pred1, pred2) =
Line 3,327:
myfunc (true, false);
myfunc (false, true);
myfunc (false, false);</langsyntaxhighlight>
 
{{out}}
Line 3,338:
=={{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,352:
uplevel 1 $bothFalseBody
}
}</langsyntaxhighlight>
Demonstrating:
<langsyntaxhighlight lang="tcl">if2 {1 > 0} {"grill" in {foo bar boo}} {
puts "1 and 2"
} {
Line 3,362:
} {
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,374:
# 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,392:
}
}
timestables 3 3</langsyntaxhighlight>
Output:
<pre>
Line 3,410:
{{trans|CommonLisp}}
 
<langsyntaxhighlight lang="txrlisp">(defmacro if2 (cond1 cond2 both first second . neither)
(let ((res1 (gensym))
(res2 (gensym)))
Line 3,418:
(,res1 ,first)
(,res2 ,second)
(t ,*neither)))))</langsyntaxhighlight>
 
=={{header|UNIX Shell}}==
Line 3,424:
 
{{works with|Bourne Shell}}
<langsyntaxhighlight lang="bash">if2() {
if eval "$1"; then
if eval "$2"; then eval "$3"; else eval "$4"; fi
Line 3,430:
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,440:
' '
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,452:
$(body$c1$c2)
}
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="es">if2 {test 1 -gt 0} {~ grill foo bar boo} {
echo 1 and 2
} {
Line 3,462:
} {
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,482:
{{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 lang="ecmascript">class IfBoth {
construct new(cond1, cond2) {
_cond1 = cond1
Line 3,533:
}.elseFirst {
System.print("a == 1 and b <> 3")
}</langsyntaxhighlight>
 
{{out}}
Line 3,543:
=={{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,627:
equalsOneOrTwo(2);
equalsOneOrTwo(3);
equalsOneOrTwo(0);</langsyntaxhighlight>
{{out}}
<pre>
Line 3,638:
=={{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,664:
 
done:
;rest of program</langsyntaxhighlight>
 
 
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.
 
<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,679:
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
10,333

edits