Showing posts with label scotch. Show all posts
Showing posts with label scotch. Show all posts

Friday, January 28, 2011

Scotch 0.3.0 is here

I've been working hard lately to hit all of my release goals so I could get a new, improved version of Scotch out the door.

You can read about the changes (or the basics) in the new documentation. Aside from a lot of new functionality, one improvement that I'm really happy about is just-in-time compilation. This results in a dramatic speedup by greatly reducing the number of times each module is parsed. Previously, parsing accounted for all of the major cost centers affecting running time. A big culprit was std.lib, which is loaded at startup and then reloaded into every other imported module as it was interpreted. JIT compilation has resulted in about a 10x speedup for the cases I tested, making Scotch once again faster (again, for specific benchmarks being tested) than object oriented languages in its class such as Python and Ruby.

A Scotch website is in the works, but for now you can head to http://scotchlang.org which is a redirect to the front Wiki page of the Github project. Downloads are available here. And, check out the build instructions here.

Thursday, January 20, 2011

Support Scotch

Throw in a couple bucks and keep Scotch going!

You can now donate to support continued development of Scotch via Pledgie/PayPal using this button:

Click here to lend your support to: Support the Scotch programming language and make a donation at www.pledgie.com !

Scotch has been developed so far using a lot of my spare time, which I now have very little of. Scotch has already implemented some cool ideas and is definitely the first language of its kind, and there are still a lot of cool plans for the future. Your donation will be used to fund development and other direct costs (hosting, for example) associated with Scotch, and every dollar will be accounted for.

Our first goal is to acquire a used Mac Mini (around $350) so that we can build Mac packages and support Mac users better.

You can also support Scotch by helping with development, or by spreading the word.

Friday, January 14, 2011

Scotch : Haskell :: Python : C

A new programming language is useless if it doesn't solve a problem. With that in mind, I want to explore the main problem that Scotch solves.

Let's start with an analogy that expresses the basic motivation behind Scotch: Scotch aims to do for functional programming what Python has done for imperative. Or, in other words, Scotch : Haskell :: Python : C.

In terms of functionality, little of Scotch is new, although I do think the type system sets it apart from popular languages. Many significant functional programming languages already exist: Haskell, the Lisp family, the ML family, F#...so why do we need a new one?

Fortunately, Scotch has an important use case that none of these languages covers: it's an easy-to-use scripting language. Scotch is interpreted, its syntax is intuitive, its type system won't fight you, variable definitions can be redefined, and types never need to be declared: all features it shares with Python and Ruby, not other functional languages. A good developer equally familiar with Scotch and Haskell or Lisp or some other functional language will be able to throw a simple project together faster in Scotch. I'd also wager that, all things equal, this developer would be able to develop faster in Scotch than in Python, just as Python enables faster development than C.

Why?

I like to compare Scotch to Python; both are basically a bundle of things that have been done before, but both emphasize readability and developer productivity as two major selling points. Python achieves better readability in part by using simple, intuitive syntax. I would say that Scotch goes even farther in this direction because its syntax is almost identical to the most common, understandable notation in existence: math.

Take this example of function definition. In Python:

def area(length, width):
    return length * width

In Haskell:

area :: (Int a) => a -> a -> a
area length width = length * width

Scotch:

area(length, width) = length * width

And in math:

A(l, w) = lw

To avoid identifier ambiguity, the Scotch version is not quite the same as math, but I'd say it's close enough. Comparing the first three, the third is more concise; to anyone with a basic math background, it is also more intuitive.

Computer programs express mathematics. Historically, programming languages have contorted mathematical notation to do things we wanted to do. With Scotch, the program looks like the math that it expresses. I believe that scientists, mathematicians, or anyone who uses math in their daily lives (that's everyone) will be able to read and understand a Scotch program - instead of learning a new "language," they simply have to learn how to apply a language with which they're already familiar.

I didn't develop Scotch to be popular; I invented it to scratch my own itch, creating a kind of hybrid of two of my favorite languages, Haskell and Python. At the moment, I've written more Scotch than anyone else on Earth (and I imagine it will stay that way for some time). The verdict: I've found developing the Scotch standard library to be a refreshingly painless experience compared to other languages I've worked in.

Sunday, January 9, 2011

Scotch 0.2.0 is out

School starts tomorrow, so my spare time is going to disappear for a bit. With that in mind, I'm packaging Scotch as version 0.2.0 as a release at GitHub (head to the "downloads" page.)

For help getting started, check out these code examples.

Version 0.1 was a prototype that I released just to get something up. Some significant improvements in 0.2.0 include:
  • Significantly more efficient - features like tail recursion and a hash table for variable/function bindings enable version 0.2.0 to run much faster
  • File input/output
  • Support for threads
  • Implemented hash tables
  • Algebraic data types
  • Anonymous functions
  • Expanded std.lib with more useful functions
Plans for the future include:
  • Native implementation of Scotch interpreter, in Scotch
  • Scotch-to-C compiler
  • Just-in-time compilation to an intermediate format - this will likely result in about a 50% speedup
  • Systems programming
  • Infinite lists

Monday, January 3, 2011

What's New with Scotch: 1/3/11

Here's a summary of some new features that have been recently added in Scotch:

Threads
Scotch now supports lightweight threads (lwt), which currently borrows from the Haskell lwt model. They can be used like this:

>> thread (do print 1; print 2; print 3;)
1
2
3
>> a = do print 1; print 2;
>> b = thread a;
>> execute([b] * 2)
1
2
1
2

Currently, state is not shared between threads; some sort of simple shared variables is needed, and it's on my to do list.

Algebraic Data Types
The ADT model is considerably different from other functional languages because of Scotch's type system. For object-oriented programmers, ADT are kind of like lightweight classes that you don't need to define before you use (but without encapsulation - in functional programming, behavior is handled by functions, not methods.)

For example:

>> Apple
Apple
>> Apple 1
Apple 1
>> Apple (Banana(1,2,3))
...

So, a custom type is an Atom (WhichLooksLikeThis) followed by any number of values (if there are more than one, parentheses are needed to eliminate ambiguity.) These custom datatypes can be used in function pattern matches like so:

>> a = Apple 1
>> f(Apple a) = a
>> f(a)
1

This pattern matches Apple followed by a value, and binds 'a' to that value.

Anonymous Functions
Wherever a function would be passed as an argument, like in this example...

>> apply(f, x) = f(x)
>> apply(add(10), 5)
15

...an anonymous function can also be used, which looks like this:

>> apply(a -> a + 10, 5)
15

This allows you to define functions without binding them to a variable. (Incidentally, these functions are a type of value, so they can be bound to a variable if you feel like it: f = a, b -> a + b)

Sunday, December 19, 2010

Intro to Scotch

Over this Christmas break, I've been developing a new programming language, Scotch (available at Google Code GitHub). It started out as just an exercise to understand language implementations better but I got a little carried away. The goal is to create a functional programming language that's easy to use to quickly throw something together with, with highly readable syntax a la Python. Here are a few of the language's cool features, especially for those who are unfamiliar with functional programming:

First, assignment can be done lazily or eagerly. Imperative languages (most popular languages nowadays) assign values eagerly, which means that when you say a = b you're really defining a as the current value of b. If b changes, a will remain the same. With lazy evaluation, a is simply defined as the expression b, which will only be evaluated when a is needed. You can do things like this that would raise exceptions in imperative languages:

>> a = b
>> b = 6
>> a
6

(Note: >> designates a line entered in the interpreter. Anything beneath is the value returned.)

So, variables can be defined in an order-agnostic way. I deviate from absolute pure functional languages like Haskell in that variables and functions are allowed to be redefined; in practical applications, some state is unavoidable, so Scotch allows state without having to pull teeth.

Pattern matching is also a really cool way to represent functions. Say, for example, we're constructing a factorial function (not especially useful, but I like to use this as an easy example.) Based on the definition of factorial, we can define it like this:

fact(n) = n * fact(n-1)

The result is a recursive function that calls itself with smaller and smaller values of n. Unfortunately, this function will continue forever, calling itself with values down to negative infinity. How do we tell it to end? In an imperative language, you could use if, like so:

fact(n) = if n == 0 then 1 else n * fact(n-1)

But, with pattern matching, we can define the function differently when the value of n is 0, like this:

fact(n) = n * fact(n-1)
fact(0) = 1

When the function is called, it checks the most recent definition to see if it's a match: if n is 0, it will match and return 1. If n is not 0, it will match to the next definition, where n can be anything. Not only is this version shorter, but to me, the meaning is much clearer here - and as the complexity of the function increases beyond that of a simple factorial function, the benefits to readability become more obvious.

Just about the entire Scotch standard library is written in this fashion, using (tail) recursive functions. Any function, from getting the length of a string to getting the rightmost n characters, can usually be represented as a general definition plus a base case that tells the recursion when to stop.

Patterns can also be used to split lists and strings. For example,

head(h:t) = h
tail(h:t) = t

In this example, the pattern is two variables, separated by a colon. When a list or string is passed as an argument to these functions, the first element/character becomes h, and the rest becomes t. This means you can do what you want with h, then call the same function on the rest of the list/string, to manipulate a string or list item by item.

Finally, in Scotch, functions are values, and so are partially applied functions. Let's look at a few examples of passing functions as arguments to other functions:

>> apply(f, x) = f(x)
>> g(n) = n
>> apply(g, 10)
10

The function g is passed as an argument to the function apply, and then called with the argument 10, returning g(10) which equals 10.

Partially applied functions are function calls to which we will add more arguments later. For example:

>> apply(f, x) = f(x)
>> add(x, y) = x + y
>> apply(add(10), 20)
30

Normally, add(10) wouldn't be a valid function call, because there's no definition of the add function that only takes one argument. But in this case, add(10), a partially applied function, is called with another argument, 20, resulting in add(10, 20), or 30.

For developers coming from imperative languages, imperative-style procedures ("procs") can be defined like so:

print_number(n) = do  a = "The number is " + n;
                      print a;

This capability relieves a bit of a pain point with pure functional languages such as Haskell, the use of monads to handle IO. Here, IO can be interspersed within regular code, which, among other things, makes quick debugging much easier.

Notice, also, that Scotch is weakly typed, meaning a number "n" can be added to a string without having to explicitly convert it to a string.

Anyway, that's Scotch so far. There are still some things that need to be implemented - notably concurrency, systems programming, and non-file I/O.

Monday, December 13, 2010

Introducing: the Scotch programming language

I worked through the initial chapters of Programming Languages: Application and Interpretation by Dr. Shriram Krishnamurthi of Brown recently. It was meant to be just an exercise, but I got really into it. From the beginning I did things completely differently from the way they're done in the book - I did everything in Haskell instead of Scheme, which involved writing a parser (definitely more involved than I realized), and my functions and variables were lazily evaluated from the start and utilized a much different form of lexical scope. I ended up coding up a working language interpreter and thus my new programming language, which I'm calling Scotch, was born. ("Scotch" is a veiled reference to the Glasgow Haskell Compiler, or whiskey, or scotch tape, or whatever else you want it to be.)

I'm convinced that functional programming is the way of the future, but functional languages sometimes seem pretty scary to newcomers (Lisp's parentheses, Haskell's monads, etc.) Functional programming needs a language that can do what Ruby and Python did for object oriented programming, a quick "prototyping" language with lots of power and few rules. The idea behind Scotch is to create a language with the readability and syntax of Python, but replacing support for object oriented programming (completely, to discourage its use) with functional tools such as lazy evaluation and recursion.

I'm trying also to deal with some common complaints about functional languages. For example, there is a simple print statement, and the syntax looks very similar to Python, although there are differences behind the scenes. Also, functions and variables can be defined more than once, so variables are capable of incrementing, although the default assignment is lazy so too much reliance on state is discouraged. And duck typing, one of the features which makes scripting languages so convenient, is also available.

The interpreter works, although you couldn't do much with it just yet. You can check it out on the Scotch page at Google Code.

Hopefully I'll be able to implement some more features to make it usable before I get too busy with next semester's classes.