It just struck me how magical certain constructs and idioms must feel like for a “hard core” C developer when entering more abstract and/or functional and/or dynamically bound settings. It is also interesting how many – most? – people living daily in this more “modern” (I should use the word Indirect) world of tools and methods still consider some of these constructs as too magical and/or redundant to use, and often, incorrectly, believe such magic must inflict a runtime performance.
I try to perform a time shift here, taking my mindset back some 20+ years when I – as a curious junior C/Pascal developer – entered the world of object orientation, recursion and symbolic languages, and imagine what constructs in this Indirect development environment of today I would consider most magical back then.
Here they are, in order of less-to-more magical, where some of this magic build on other (less mystical) magic:
- overloading – having two functions with the same name but just having different kinds of parameters!
- callback – not calling a function, but passing its address to another function or even stored inside a structure, for deferred call!
- events – telling a “framework” to invoke a callback whenever a specific event occurs, not necessarily controlled by my code!
- nested function calls – not storing the value of one application in a variable, but using the applicative expression directly as an actual parameter to another (or even the same!) function!
- recursion – having a function calling itself, even though the function is evidently not defined yet!
- abstract data types – just accessing a structure via specific functions instead of groking the interior directly, enabling for distinct structure layout without callers being aware!
- objects – being able to send a “message” to a structure and have something happening, like a mini application in itself!
- dispatch polymorphism – having two distinct implementations for the same function call without the caller even being aware!
- introspection – looking into the actual underlying implementation of types and functions, such as what arguments a function expects, in runtime – without resorting to assembly code!
- reflection – actually changing the implementation of a type or function from within the application in runtime!
- dynamic loading – code loaded from different places into the process at run-time!
- hot code swapping – being able to change implementation while application is running, via dynamic loading!
- code versions – two distinct implementations of a type or function at the same time in the process!
- inheritance – using existing implementations for most functions but replacing some without the caller being aware!
- mixins – being able to add some behavior to a type, alongside its main functionality, via “multiple inheritance”!
- closures – creating a function, perhaps even on-demand, without a name and being sensitive to variables in the environment created!
- currying – having a function expecting a bunch of parameters to produce anything real – number, text etc. – and only supplying some of them, deferring that “real” value till later!
- pattern matching – having case analysis being automatic based on syntax while extracting parts of the structure at the same time!
- function values – no qualitative difference between a number and a function, being able to store or pass a function!
- higher order functions – actually defining a function that needs help, at call-time, from a passed function, to do something concrete!
- one-time assignment – not being able to assign a variable twice!
- combinators – taking two functions and combining them into a third one, with the power of both embedded somehow, for later invocation, without any mentioning parameters!
- templates – using the same code for different types where code is created on demand, when using it for a specific type!
- specialization – being able to bypass the default template implementation for specific types, and even doing so for a group of types, called partial specialization
- type inference – having types without having to type them, the machine automatically deduce them for you!
- polymorphism – having a type or function being defined in one place while being able to act differently depending on the type of values involved!
- generic concepts – being able to say something about the “kind” (concept) of types (models) a function expects without mentioning the type itself, and instructing how a specific type – even primitive types such as numbers – fit that concept!
- functors – mapping a type to another one through a meta function!
- catamorphisms – taking an operation on a primitive value and semi-automatically “lifting” it to a more complex field, often being aggregates of the former type!
- monads – avoiding direct side effects by building up a chain of deferred actions, through the use of referentially transparent expressions, which are “then” executed, almost orthogonally to the actual buildup!
Excluded are a lot of tricks in the logic programming bag, such as uninstantiated variables being used in constructs and back-tracking.
Anyway, in order to test out this voting mechanism in WordPress, which trick above do you think is
- most useful; and
- most magical/strange for a “C mindset”
Note: since my plugin has a limit of 20 potential answers, I discard the first 10, which should be trivial for most of us, i.e., their magic has long since worn off
[poll=2]
[poll=3]
Computer Science Functional Programming