match condition {
true => { ... }
false => { ... }
}
In fact you can create a language without if/else and pattern-matching, if you have something like first-class functions to handle branching. One notable example of such a language is lambda-calculus: true = λtf.t
false = λtf.f
if = λctf.ctf
Which in more familiar syntax is true = (t, f) => t()
false = (t, f) => f()
if = (c, t, f) => c(t, f)
And would evaluate like so if(true, workCorrectly, crashAndBurn)
==> true(workCorrectly)
==> workCorrectly()
However in practice, most high-level languages have if/else. Even lesser-known functional languages like Coq and Haskell which rely more on their pattern matching, still include it simply because it's convenient and easy to implement. Worst case, the compiler can (and sometimes does) just desugar the conditional into one of the above. #![feature(fn_traits)]
#![feature(unboxed_closures)]
struct If;
impl<T, F, V> FnOnce<(bool, T, F)> for If
where
T: FnMut() -> V,
F: FnMut() -> V
{
type Output = V;
extern "rust-call" fn call_once(self, args: (bool, T, F)) -> Self::Output {
let (condition, mut yay, mut nay) = args;
let arms: [&mut dyn FnMut() -> V; 2] = [&mut nay, &mut yay];
arms[condition as usize]()
}
}
https://play.rust-lang.org/?version=nightly&mode=release&edi... 3 < 4 ifTrue: [ 'true' ] ifFalse: [ 'false' ]
But very arguably that is still if-then-else, it's just not a special construct in the language. Avoiding Boolean values is also sometimes better to convey intent more precisely ("Boolean blindness"), but that's just a stylistic thing and not forbidding Boolean values entirely.You can, however, do away with else using unconditional branches - a.k.a. "goto". Pseudocode:
goto :positive if input > 0
goto :negative if input < 0
print "Got zero"
goto :end
:positive
print "Got a positive number"
goto :end
:negative
print "Got a negative number"
:end
Whether this is an improvement is questionable, but I've seen some industrial and enterprise systems with their own "graphical" languages that do this. I've also seen (in similar environments) the inverse where everything is an if/else (or pass/fail), like so: start: compare(input > 0) pass: positive fail: next
: compare(input < 0) pass: negative fail: next
: out("Got zero") pass: end fail: end
positive: out("Got positive") pass: end fail: end
negative: out("Got negative") pass: end fail: end
end: exit() pass: next fail: nextMy idea is, wrap an expression, then calculate if it's false then automatically try catch.
The only way I see about avoiding that is by having the language target a "MOV machine" - that is, one where the only possible operation is to move values to/from memory. Conditionals would then work by writing values to predetermined addresses, reading a result from some predetermined address, and writing that result into the instruction pointer. This is cheating, of course (you've only punted the "if"s to the machine itself), and I wouldn't exactly call it "high-level", but it does technically satisfy the criterion of the language itself having no concept of a conditional jump (so long as it remains blissfully unaware of what the addresses it's reading/writing actually mean).
IOW one should expect all computing languages to have some form of conditional branching because it is an elemental part of the logic capability of any CPU.
Generally, this type of refactoring converts code to a more declarative style: tell the computer what to do instead of how to do it (if-then-else): https://www.wikiwand.com/en/Declarative_programming
So you're probably looking for a declarative programming paradigm. (A single programming language can support multiple paradigms.)
def print(true), do: IO.puts("true")
def print(_), do: IO.puts("not true")
In fact it's typically best practice to do this. I almost never write if statements in elixir. It makes chaining much easier.
value |> change_1() |> change_2() |> print()
I mean you can sugar up if as "when" or "cond" or "unless," but unless you have conditional branching you won't really have logic within the program.
More philosophically, a language that doesn't have conditional branching will still be running on hardware that has it, so long as it is running on a computer.
Good luck.
It was certainly an idea that was in the air at the time; computer science was developing rapidly and of course everyone read everyone else’s papers and collaborated with each other. McCarthy, the inventor of Lisp, was also the one to propose structured conditionals for Algol-58, though it wasn’t accepted until later.
Lisp was unusual in that it had 10 things that no other languages of the day had:
1. Structured conditionals 2. First–class functions 3. Recursion 4. variables are pointers, only values are typed 5. automatic Garbage Collection 6. no statements, only expressions 7. symbols as a data type distinct from strings 8. all code is entered as a syntax tree (homoiconicity) 9. full language available at load, compile, and run time 10. Macros
Most modern languages have adopted most of these, with few exceptions. Systems languages (like Rust) often forgo automatic garbage collection (for good reasons), and nobody does macros as well as Common Lisp. Homoiconicity is quite rare outside the Lisp family of languages, as is having the compiler be part of the run time. On that latter point, Javascript comes the closest; you can go into the dev tools and define a new function that will be JIT–compiled along with all the rest, even if there is no specific function you can call to compile some code, or to disassemble some compiled code. It has an `eval` function you can use to read and evaluate new code from strings. In Lisp this is broken into two functions, `read` to parse code (or data) out of a string and produce list structure, and `eval` which executes code which has previously been parsed by `read`, or constructed by a macro, etc.
(if predicate consequent alternate) might be missing in favour of only (if predicate consequent), or you might only have the variadic form (cond p0 c0 p1 c1 p2 c2 alternate).
It has no conditional methods. It's a very straightforward step by step process that just ends when you don't have any more steps.
I've written a few emoji reaction workflows.