When we write this in C: How should »eval« behave, when
a called »malloc« returns 0? The usual good practice in C
is to report such a failure to the caller. But the return
value of »eval« already has another meaning.
Moreover, when should the graph allocated by »eval« be
deallocated again? In »print«? But what should one then
call the next time one wants to print a value /not/
deallocating it?
So the need to check allocation attempts and to manage
dynamic memory in C makes such wording as
»print(eval(input()))« difficult in C.
Also, in C, blocks are not functions, so one lacks
function literals (anonymous functions) in C and
one also lacks lazy evaluation of arguments (see below).
encapsulation, easy. polymorphism is a bit harder. You can do
some nasty things with structs but I'm not sure it's worth
it. Could you do some sort of Duck Typing?
You can do everything you can imagine, but when using it
in C itself, the wording might be more complicated. In a
pure object-oriented language (POOL), even blocks are
objects, so, in Smalltalk, one can implement a custom if
statement with a custom boolean type that can be used as
a > 0 ifTrue: [a := 0]
. This will set »a := 0« if a > 0. In C, one cannot write
( greater( a, 0 )->ifTrue )({ a = 0; })
since blocks are not expressions, one would need to write
( greater( a, 0 )->ifTrue )( set( a, 0 ))
using a function call. But since, in C, arguments are
evaluated always, this would always set a to 0. We don't
have lazy evaluation in C for function arguments. This
also applys to the question of writing in a PFL style
in C. (PFLs and POOLs have some thinks in common.)
Moreover, »greater( a, 0 )« was assumed to return a
structure with a function pointer »ifTrue«, that needs to be
allocated dynamically. This also raises the question how it
should report a failure due to lack of memory and how that
memory should be managed after a successful allocation.