Monday, December 27, 2010

Programming is Easy (Usually)

I read the Daily WTF sometimes, and I have to say: the only things they can complain about is "quirks" of the language they're using: exceptions make control flow hard to follow, rand() isn't referentially transparent, lack of syntax sugar, etc. etc.

These are bugs; they happen to be located in the programming language design. But you can still fix them. Stop complaining, start programming. Seriously.

The problem is that languages are considered to be "hard"; this probably comes from examples in the past.
  • C/C++ (namely GCC) was specifically designed to be messy and hard-to-modify, so that proprietary software can't interface with it.
  • Javascript (in general, any committee language) has too much red tape to modify it (e.g. "let" isn't used because it's not cross-browser)
  • Perl/Python/Ruby are constructed around "philosophies" rather than fixing problems in languages (i.e. they reject language patches)
  • "Small" languages are designed by academics, and are guilty by contamination (Lisp, Io, etc.)
So it's wrong; fixing bugs is easy. You just have to solve all these other "human" problems to get it accepted, which is supposed to be hard for programmers. Think "geek in the basement"; is he going to spend time advocating for his patches when he could just keep on hacking? Thus one ends up with a fragmented ecosystem of good programming; lots of people, working on their own, who nobody pays any attention to except to reject. And they don't say that it's easy, so it's hard.

Does the conspiracy to keep programming difficult sound extreme yet? Subscribe for more!

Sunday, December 12, 2010

Link dump

This is pretty much everything I'm going to dump into the language core:

Thursday, October 7, 2010

Sets are values

As well as being functions, set are values. You can apply functions to them, pass them around, etc.
Wait, what is {1,2} + 2, you ask?
Simple: it is just {1+2,2+2}={3,4}.

Similarly, {...,-3,-2,-1,0,1,2,3,...} * {2,3} = {...,-9,-8,-6,-4,-3,-2,0,2,3,4,6,8,9,...}.
It's just that set monad or ambiguous choice that you thought might be cool.

But sets are types, so this means you can do type-level arithmetic; (2 * Integer) * 3 = (6 * Integer)
Of course, this probably makes the type system undecidable... but I certainly don't care!

Saturday, October 2, 2010

Software VC

Since software is change, it stands to reason that good software should have lots of change, right? It should be easy to change, fun to change, quick to change, etc.

The current method of software distribution, namely binary executables, is not that good a format then. Neither is text, since you can't run it. So something else must be devised... a distributed environment? a serialization format for objects over the network? I have no idea, yet. But commit logs are pretty useful; something like that format would be cool.

Problems and their solutions

Search time! Programming language problems and my solutions for them:
Programming language problems
Programmers are stupid -> make them users. (who are even more stupid!)
No paradigm is complete -> continuously invent new ones
Performance -> whole-system optimization
Three programming language problems solved forever (using HQ9+)
Incrementing a register: ++ (implicit stack)
Hello world: "Hello world!"
Quine: "There is no source", so quines are meaningless. But hacking up something legible won't be too hard.
99 bottle of beer on the wall:
bottlefunc = {
  0 -> "No more bottles"
  1 -> "1 bottle"
  x -> x " bottles"
}

99..0 | bottlefunc | {
  x " of beer on the wall, " tolower(x) " of beer;\n"
  (x == 0) ? "Go to the store and buy some more, " x.first " of beer on the wall."
           : "Take one down and pass it around, " tolower(x.next) " of beer on the wall."
}
Important things for a programming language to have
Unicode support: This is all about how you define a character. And, as it turns out in Unicode, there are no characters, there are only code points, integers from 0 to 10FFFF. And there are all sorts of code points that have no resemblance to characters; byte order marks, zero-width spaces, text direction overrides... such a pity that there are no conditional characters to make it Turing-complete!
Anyways, I am certain you see that Unicode is large enough to be put in its own separate library. So that is where Unicode will be, and the language will remain close to the keyboard. (which appears to be close to ASCII)
The problem Self solves
The duality between classes and instances creates a problem. But classes, as depicted in the link, are data structures. So, logically, if removing classes is a good idea, so is removing abstract data types, unions, records, and the other data structures we know and love hate.

Sets are functions

Sets are functions of type a -> Boolean. Stating that sets are well-defined is equivalent to stating that their function terminates.

Types are sets and sets are types

The essential property of a type is whether a value belongs to it. So too with sets. So let a ∈ S be the same as a instanceof S.
Subtypes are subsets.
Function types are special subsets of set tuples.
(Disjoint) set union is the sum type
The Cartesian product of two sets is the product type of the two types.
Set equality is type equality
The power set is the type of subtypes.
The universe set is the set of all bit patterns.
Set intersection is interesting and does not appear in any language I know of, other than subtyping.

I am not certain what the axiom of choice says when applied to types; it is probably rather profound.

Tuesday, August 10, 2010

Update

Long time... no posts... but I'm still here, reading and thinking (as of July 31, 2014).
  • I need a pretty good parser; Stanford NLP is probably the closest thing. Unfortunately it has to be near-universal so building the required training set could take some time.
  • LLVM could be taking over the world; if so, I could get the universal compiler and runtime I need
So perhaps the ultimate programming is not too far off. Must investigate further...

Tuesday, March 23, 2010

Examples from RosettaCode

Type equivalence:

(a == b) = true
(a == b) = false
(b) a or a.castTo(b) will return a value of type b or an error (of type b).

Eval:

eval(\" x \") = x // define an eval (uses current scope/environment)
x = 1
eval("x") // 1
eval("x+1") // 2

// you can provide type safety
pure(eval("print \"x\"")) // error (with no value)
pure(eval("\"x\"")) // x

// ^ pure is a cast from an impure function to a pure function, obviously

// you can create another eval with null scope:
// This is probably not what you want, as the null scope won't do anything
evalEmpty = {
  eval = eval;
  #parentScope=null;
  eval(x)
};

evalEmpty("1+2") // 1+2 - I told you it doesn't do anything!

evalWithScope = {
  parentScope = scope;
  eval(x)
};

evalWithScope(rootScope, "1+2") // 3
evalWithScope(#scheme#.rootScope, "(+ 1 2)") // 3
x = 1+2
evalWithScope(currentScope, "x") // 3
Scopes include rootScope, #language#.rootScope, and currentScope. You can get more complicated if you want by creating other scopes.

Ethiopian multiplication:

half(x)   = x >> 1   // pointfree: half =  >> 1
double(x) = x << 1   // pointfree: double =  << 1
even(x)   = x % 2==0 // pointfree: even = ! (% 2)
ethiopian(x,y) = (even(x) ? 0 : y) + ethiopian(half(x), double(y))
x ethiopian y = ethiopian(x,y)

Link time:

Link time will occur between program input and execution at any time that files to link have been specified.

Tclkit:

One file suffices for execution of programs.

FIFO (usage):

// Init

// pick your favorite constructor
fifo = new List()
fifo = List()
fifo = List
fifo = []

// Error handling
x = peek(fifo) // x = underflow
x = pop(fifo)  // x = that same underflow
index = fifo.push(x) // index = -1, fifo[index] = x = underflow. get it?
empty(fifo) //true
x,fifo2 = pop fifo // if you're not a fan of mutation or parenthesis
fifo2 == fifo // false; underflowing is not ignored

// Normal usage
fifo.push(1)  // fifo = [1]
push(fifo, 2) // fifo = [2,1]
pop(fifo,x) // x = 2, fifo = [1]

no = empty(fifo) //y = false
empty(fifo) = true // empties fifo
x = fifo.peek() // x = underflow
/* fifo.empty = false */ // gives a type error
fifo.empty = no // fifo returns to previous state

pop(x, fifo) // x = 1

Amb:

// Some cool list syntax
set1 = "the"    | "that"     | "a"
set2 = "frog"   | "elephant" | "thing"
set3 = "walked" | "treaded"  | "grows"
set4 = "slowly" | "quickly"

a/"(.*)(.)"/ amb b/"(.)(.*)"/ = (a$2 == b$1) ? a " " b

print (set1 amb set2 amb set3 amb set4)

Dynamic variable names:

name = in.readString();
this[name] = 1; // due to table-object correspondence

API's:

I will steal borrow them from other languages!

Simulate mouse click:

System.Hardware.Input.Mouse.click(x,y)
Namespaces because I feel like it. Acceptable targets depend on privilege level and where/how you got x and y.

Run-length encoding:

#brace-style python // because I just don't care anymore
for(x in string)
  run = 1
  while(x == x.next)
    run++
    x = x.next
  out << run << x

Inheritance:

Animal = { eat, noise }
Dog = Animal
Dog.noise = "Bark!"
Dog.eat = "Dog chow"
Lab = Dog
Collie = Dog
Collie.eat = "Scraps from the table"
Cat = Animal
Cat.noise = "Meow"
Cat.eat = "Mice"

// = is a pretty powerful operator

Apply a callback to an Array:

array.each(callback)
callback(array)
array | callback
map(array, callback)
for( i in array ) callback(i);

Environment variables:

System.Environment["TEMP"]
Dependent once again on privilege level

Bitwise operations:

// because bit operations are byte operations
a & b = {{00}{01}}[a][b]
a | b = {{01}{11}}[a][b]
a ^ b = {{01}{10}}[a][b]
~a    = {10}[a]
// add more here...
a << b
a >> b
a >>> b
rotateLeft(a, b)  // a >^ b ?
rotateRight(a, b) // a ^< b ?

Conway's Game of Life:

grid[_,_] = 0
grid[2,1..3] = 1
neighbors[livecount,cellvalue] = 0 // livecount includes the cell itself
neighbors[3,0] = neighbors[4|3,1] = 1

do {
  print(grid);
  newgrid[x,y] = neightbors[sum(grid[x-1..x+1,y-1..y+1]),grid[x,y]];
  grid = newgrid;
} to 3;

Simple Random Distribution Checker:

srdc(generator, times, delta) {
distribution = {};
do {
  distribution[generator.next()]++;
} to times;
distribution /= times;
skew = (max - min)(distribution);
if( skew / 2 > delta)
  print(error)
}

Wednesday, February 24, 2010

License

I always worry about what license to release a new language under. There are too many licenses and not enough languages. (or maybe I have that backwards?)

A (biased) summary of some licenses:
  •  GPL
    • My language is so unique and powerful that only open-source programmers should be able to use it.
    • My language is complete enough that you won't need proprietary programs.
    • Beg and plead with me, and I might give you a better license
    • I will eat your children!
  • LGPL
    • You can use my language, but don't expect support unless you're contributing.
    • yadda yadda yadda
  • BSD
    • I don't care what you do
    • This project doesn't do much...
    • etc.
  • WTFPL
    • I don't care what you do.
    • Do it.
  • CC-BY-SA
    • What? Some weird person...
    • My software, use it if you want
  • CC0
    • free stuff!
I still don't know which one I want...

Thursday, January 21, 2010

Task List

  • Create universal language
    • Status: Not yet started
    • Possibility: x86
    • Requirements:
      • supports all known language constructs - INCOMPLETE
      • converter from previous languages - INCOMPLETE
  • Build universal compiler
    • Status: Not yet started
    • Requirements:
      • supports universal language - INCOMPLETE
      • supports all architectures - INCOMPLETE
      • fast - INCOMPLETE
  • Open universal editor
    • Status: Not yet started
    • Requirements:
      • supports universal language - INCOMPLETE
      • intuitive - INCOMPLETE
My task list (could take a while)

Sunday, January 10, 2010

Wisdom

Wisdom can be found in many places.
A: Calc. III took my virginity.
B: It found the area under your curves?
Apparently a bathroom stall is not one of them.