3 ms·
I see what you are getting at that basing a programming language on one dialect like english is a bad idea. But what I disagree with is that pure mathematics i
by zackmorris 13y ago
I see what you are getting at that basing a programming language on one dialect like english is a bad idea.
But what I disagree with is that pure mathematics is more useful than other ways of thinking. Anymore, I find that having to adapt myself to whatever methodology a language imposes on me is generally more work than the problem I'm trying to solve.
Take for example the current hubbub over promises to try to reduce callback hell in javascript. What I find almost amusing is that callback hell shouldn't exist in the first place. It was solved trivially thirty years ago with cooperative threads on pre-NeXT Mac OS. It's obvious in hindsight that cooperative threads were a mistake for kernels, but they turn out to work quite well for processes (the people who wrote Go realized this and did one better, adapting some of the functional concepts from Erlang into a cooperative-thread style that can run concurrently because there's little or no shared data). You rarely have to deal with mutexes or atomic operations (except in cases where one of your operations spans a yield). IMHO they left yield out of javascript in browsers originally for political reasons, because it was already handled by the runtime. Adding it back in is a reluctant admittance that it's become a necessity in today's complex GUIs.
Anywhere I look today, I see these problems revisited that were really solved in better ways years ago. A great example of dogma today is templates in c++. Such an astonishing amount of boilerplate to do things that are so easy in other languages, or with more fine grain control of macros. And a lot of the verbosity goes away when you allow variables to infer their type from the return value of a function. Statically typed variables are even a form of dogma. What matters is the underlying piece of data, not the name of the variables that refer to it. We should be dealing with things as a large graph where the data is hashed or referenced somehow if we need a name for it. Honestly most of the code I write now doesn't even have variables. I only use them when I have to work around a limitation of the language (for a long time php wouldn't let you use the array access [] operator after on function result) or when a piece of code is too large to fit on a line. Variables themselves don't actually exist, they are an abstraction. If C had a way to make a const type and initialize it later, we could emulate many of the advantages of functional programming by using the variable name to refer to the result of a block of code. Another example are the blocks in objective-c, which are just nested anonymous functions or lambdas. These should have been part of the c standard from the very beginning, but with nicer syntax (like javascript). I think they were left out for political reasons, because someone early on recognized that they would lead to callback hell! How messed up is that?
I could go on almost forever on this stuff. Lisp gets around most of these problems easily, but to me it's the mathematical equivalent of machine code. Haskell and Scala try to make it more readable but fail due to their obsession with brief notation. Conceptually none of this stuff is all that complicated. I remember the first time I saw someone using Excel and when it hit me what they were actually doing, it shook my world so fundamentally that for a moment I thought that everything I learned in computer science had been a waste of time. That feeling never quite left me.
If I had a hope for computer science today, it's that we would take the sheer simplicity of functional programming (graph-style like Excel) and build layers above it that extend a programmer's leverage. Here are a few examples off the top of my head:
* Dealing with everything as an array to provide inherent parallelism in Matlab
* Making concurrent programming look single-threaded by using select in Go
* SQL queries to retrieve data by its relationship, not its address
* Triggering actions to run when something changes like Prolog
* Dealing with atomic messages instead of streams like in Go
* Memory-mapped IO instead of loading files into memory
* Using pure sockets/file descriptors and pipes instead of proprietary APIs to access data (also pipes are just double-ended file descriptors if we could truncate from the front, and shouldn't exist as a separate concept)
* Tying objects to their representation, for example changing the visible attribute in javascript and seeing the element appear instead of calling a setVisible() function (in a fundamental way to ease the burden on programmers, not just syntactic sugar)
* Lazy evaluation/referential transparency (treating code like data and vice versa)
* Nested languages like Terra instead of writing glue (calling c from lua the way we used to call asm from c)
* Universal JIT compilers so we can quit arguing about one language being faster than another and focus on abstract concepts
* Integrating genetic programming into languages so we can express a function by its desired input and output instead of having to write every line of code by hand
* Losing the concept of a file altogether and focus on state like CouchDB
* Make all of this readable by treating the language as a view of the code (for example switching to tabs showing other views like prefix/infix/postfix or human readable like Hypertalk)
* Begin thinking of code as pruning a tree instead of manually solving the problem (let the computer explore every permutation of the problem space and return the results for review like solving equations in Mathematica x = yz -> y = x/z -> z = x/y)
* Standardize the way libraries communicate (Python should be able to talk to Wolfram Alpha and feed the results into a shell script then save each line in a SQL database with full unicode support)
* Get rid of drivers and adapt something like HTML for all devices so that they can be queried, controlled and listened to
This got way too long so I will stop there. It needs to be rewritten but I don't have time..
- MaxGabriel 13y agoI wasn't sure entirely what you were getting at with const variables in C that are initialized later – and this doesn't fit your bill, if you were referring to lazy evaluation – but you can do something like this (apparently works for Clang and GCC): const int test = ({ int a = 1+1; sqrt(a); });
- zackmorris 13y agoOh wow I didn't know about that notation! For anyone stumbling onto this, I wanted to elaborate on what I was getting at with regard to functional programming in c. When I learned Scheme back in the 90s, they had us do a lot of expressions like this: (* 1 (+ 2 3)) => 5 But I always thought it was a kind of obfuscation. They didn't mention the "define" keyword or that we could break things up into multiple lines until later in the class than I would have liked. They wanted us to think in terms of transformations on the data instead of sequential operations on it. So we were writing these enormous functions enclosed in a single parentheses that were terribly hard to decipher. This can be written as: (define a (+ 2 3)) (* 1 a) => 5 So I always wanted something similar in c, being able to write code in a functional manner without having to have these unreadable one line functions. I just wanted to store the result of a computation in a temporary const variable to break things up a little. I also didn't want intermediate variables polluting my scope. For example: const int test; { const int a = 1+1; test = sqrt(a); } => "Read-only variable is not assignable" But your notation makes this possible (slightly embellished to show the power of it): const int someOtherResult; // 41 const int test = ({ const int a = 1+1; sqrt(a) + someOtherResult; }); => test = 42 Now we can break up our statements and as long as we use only const variables and don't use any global variables, we are programming in a functional manner, for the most part. Cool! Unit tests become trivial to write, static analysis finds most of our bugs, we don't have to use as many templates.. Then if we add lambdas/closures from C++11, we can pass around code as variables and we are getting most of the benefit of pure functional languages without being so restricted in syntax. The main drawback is that we lose lazy evaluation, but in the real world that hasn't hindered me except when I was dealing with databases. Supposedly java can retrieve database results lazily but I don't know quite how that works. Perhaps something like it could be adapted for c. P.S. does someone know the name for the "({" notation? I couldn't find it anywhere thanks!