SuperCollider is an environment and ProgrammingLanguage for RealTime audio synthesis. SuperCollider is like SmalltalkLanguage but with a syntax coincidentally similar to RubyLanguage. SC has a real-time GarbageCollection, constant time message lookup, LexicalClosures, CoRoutines, default argument values, variable length argument lists, any order keyword arguments, both LexicalScoping and DynamicScoping, closure creation via partial application (i.e., explicit CurryingSchonfinkelling), TailCallOptimization, ListComprehensions.
"Hello, World!".postln; { SinOsc.ar(800, 0, 0.1) }.play; // play a sine wave at 800 Hertz, 0.1 amplitude // fork a thread that prints out 0 to 10 at 1 second intervals fork { (0..10).do {|i| i.postln; 1.wait } } // QuineProgram { thisFunction.asCompileString ++ ".value" }.value // a quine that is not a cheat. submitted by Jens Gulden { |a="", b=""| if (a!="", { a ++ "\"" ++ a.escapeChar($\\).escapeChar($\") ++ "\", \"" ++ b.escapeChar($\\).escapeChar($\") ++ "\"" ++ b }, { thisFunction.value("{ |a=\"\", b=\"\"| if (a!=\"\", { a ++ \"\\\"\" ++ a.escapeChar($\\\\).escapeChar($\\\") ++ \"\\\", \\\"\" ++ b.escapeChar($\\\\).escapeChar($\\\") ++ \"\\\"\" ++ b }, { thisFunction.value(", ") } ) }.value") } ) }.value // yet another quine {|x| x ++ '.(' ++ quote(x) ++ ')' }.("{|x| x ++ '.(' ++ quote(x) ++ ')' }")accumulator generator in SuperCollider. see Paul Graham's web page http://www.paulgraham.com/accgen.html
~foo = {|n| {|i| n = n + i }};Using ListComprehensions :
Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house that contains only five floors. Baker does not live on the top floor. Cooper does not live on the bottom floor. Fletcher does not live on either the top or the bottom floor. Miller lives on a higher floor than does Cooper. Smith does not live on a floor adjacent to Fletcher's. Fletcher does not live on a floor adjacent to Cooper's. Where does everyone live?
( z = {: [baker, cooper, fletcher, miller, smith] , var floors = (1..5), baker <- floors, baker != 5, // Baker does not live on the top floor. // remove baker's floor from the list. var creates a new scope, so the 'floors' on the left is a new binding. var floors = floors.removing(baker), cooper <- floors, cooper != 1, // Cooper does not live on the bottom floor. var floors = floors.removing(cooper), // remove cooper's floor from the list. fletcher <- floors, (fletcher != 5) && (fletcher != 1) // Fletcher does not live on either the top or the bottom floor. && (absdif(fletcher, cooper) > 1), // Fletcher does not live on a floor adjacent to Cooper's. var floors = floors.removing(fletcher), // remove fletcher's floor miller <- floors, miller > cooper, // Miller lives on a higher floor than does Cooper. var floors = floors.removing(miller), // remove miller's floor smith <- floors, absdif(fletcher, smith) > 1 // Smith does not live on a floor adjacent to Fletcher's. }; ) z.next; // [3, 2, 4, 5, 1 ] z.next; // nil. only one solution
Even though SuperCollider is a class based language, it has an IdentityDictionary? class with inheritance so you can mimic PrototypeBasedProgramming in SuperCollider.
Here is an example
stolen from IoLanguage and expanding on it a bit:
~account = ( balance: 0, deposit: {|self,v| self.balance = self.balance + v }, withdraw: {|self,v| self.balance = self.balance - v }, show: {|self| postf("Account balance: %\n", self.balance) } ); ~myAccount = ~account.copy; ~myAccount.show; ~myAccount.deposit(10); ~myAccount.show; ~myAccount.withdraw(3); ~myAccount.show; ~savingsAccount = ( proto: ~account, interestRate: 0.05, compound: {|self| self.balance = self.balance * (1.0 + self.interestRate) } ); ~myAccount = ~savingsAccount.copy; ~myAccount.show; ~myAccount.deposit(10); ~myAccount.show; ~myAccount.compound; ~myAccount.show;another example:
~myObject = ( '+': {|self, n| postf("adding %\n", n) } ); ~myObject + 123prints: "adding 123"