It seems like both can be used to define functions that you can implement later, with different data types. AFAIK the major difference is that defmulti works on maps and defprotocol works on records.
What other differences there? What are the benefits of using one over the other?
Short version: defmulti is much more flexible and general, while defprotocol performs better.
Slightly longer version:
defprotocol supports dispatch on type, which is like polymorphism in most mainstream programming languages.
defmulti is a more general mechanism where you can dispatch on other things than just a single type. This flexibility comes with a performance penalty.
More on protocols
More on multimethods
Just an addition to cover the motivation, corvuscorax's answer covers the origional question nicely.
Originally Clojure only had multimethods and very early on a lot of thought went into building a dispatch abstraction that could handle all cases very well and would not force people to structure their abstractions around a limitation of the abstractions offered by the language.
As Clojure matured the desire to create "clojure in clojure" required abstractions that where at least in theory capable of producing any bytecode that could be produced by java and thus the need for protocols, a dispatch abstraction that more closely matched native Java.
Clojure has a strong "embrace your platform" ideal and protocols suit this mindset very well.
Related
I know they are dialects of the same family of language called lisp, but what exactly are the differences? Could you give an overview, if possible, covering topics such as syntax, characteristics, features and resources.
They all have a lot in common:
Dynamic languages
Strongly typed
Compiled
Lisp-style syntax, i.e. code is written as a Lisp data structures (forms) with the most common pattern being function calls like: (function-name arg1 arg2)
Powerful macro systems that allow you to treat code as data and generate arbitrary code at runtime (often used to either "extend the language" with new syntax or create DSLs)
Often used in functional programming style, although have the ability to accommodate other paradigms
Emphasis in interactive development with a REPL (i.e. you interactively develop in a running instance of the code)
Common Lisp distinctive features:
A powerful OOP subsystem (Common Lisp Object System)
Probably the best compiler (Common Lisp is the fastest Lisp according to http://benchmarksgame.alioth.debian.org/u64q/which-programs-are-fastest.html although there isn't much in it.....)
Clojure distinctive features:
Largest library ecosystem, since you can directly use any Java libraries
Vectors [] and maps {} used as standard in addition to the standard lists () - in addition to the general usefullness of vectors and maps some believe this is a innovation which makes generally more readable
Greater emphasis on immutability and lazy functional programming, somewhat inspired by Haskell
Strong concurrency capabilities supported by software transactional memory at the language level (worth watching: http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey)
Scheme distinctive features:
Arguably the simplest and easiest to learn Lisp
Hygienic macros (see http://en.wikipedia.org/wiki/Hygienic_macro) - elegantly avoids the problems with accidental symbol capture in macro expansions
The people above missed a few things
Common Lisp has vectors and hash tables as well. The difference is that Common Lisp uses #() for vectors and no syntax for hash tables. Scheme has vectors, I believe
Common Lisp has reader macros, which allow you to use new brackets (as does Racket, a descendant of Scheme).
Scheme and Clojure have hygienic macros, as opposed to Common Lisp's unhygienic ones
All of the languages are either modern or have extensive renovation projects. Common Lisp has gotten extensive libraries in the past five years (thanks mostly to Quicklisp), Scheme has some modern implementations (Racket, Chicken, Chez Scheme, etc.), and Clojure was created relatively recently
Common Lisp has a built-in OO system, though it's quite different from other OO systems you might have used. Notably, it is not enforced--you don't have to write OO code.
The languages have somewhat different design philosophies. Scheme was designed as a minimal dialect for understanding the Actor Model; it later became used for pedagogy. Common Lisp was designed to unify the myriad Lisp dialects that had sprung up. Clojure was designed for concurrency. As a result, Scheme has a reputation of being minimal and elegant, Common Lisp of being powerful and paradigm-agnostic (functional, OO, whatever), and Clojure of favoring functional programming.
Don't forget about Lisp-1 and Lisp-2 differences.
Scheme and Clojure are Lisp-1:
That means both variables and functions names resides in same namespace.
Common Lisp is Lisp-2:
Function and variables has different namespaces (in fact, CL has many namespaces).
Gimp is written in Scheme :)
In fact allot of software some folks think might be written in C++ was probably done under the Lisp umbrella, its hard to pick out the golden apples out of the bunch. The fact is C++ was not always popular, it only seems to be popular today because of a history of updates. For the lesser half of the century C++ didn't even utilize multithreading, it was where Python is today a cesspool of useless untested buggy glue code. Fasterforward a little and now we are seeing a rise in functional programming, its more like adapt or die. I think Java has it right as far as the adapt part is concerned.
Scheme was designed to simplify the Lisp language, that was its only intent except it never really caught on. I think Clojure does something similar its meant to simplify Scheme for the JVM nothing more. Its just like every other JVM language just there to inflate the user experience, only to simplify writting boilerplate in Java land.
Disclaimer
Despite the title, this is a genuine question, not an attempt at Emacs/Vi flamewars.
Context
I've used Haskell for a few months, and written a small ~10K LOC interpreter. In the past year, I've switched to Clojure. For quite a while, I struggled with Clojure's lack of types. Then I switched into using defrecords in Clojure, and now, switched to Clojure's defprotocols.
I really really like defprotocols. In fact, more than types.
I'm now at the point where for my Clojure functions, for it's documentation string, I just specify:
* the protocols of the inputs
* the protocols of the outputs
Using this, it appears I now have an ad-hoc type system (not compiler checked; but human checked).
Question
I suspect there's something about types that I'm missing. What does types provide over protocols?
Questioning the question...
Your question "What [do] types provide over protocols?" seems awkward to me. Types and protocols are perpendicular; They describe different things. Types/records define structure of data, while Protocols define the structure of some behavior or functionality. And part of why this question seems weird to me is that these things are not mutually exlusive! You can have types implement a protocol, thereby giving them whatever behaviour/functionality that protocol describes. In fact, since your context makes it clear that you have been using protocols, I have to wonder how you've been using them. My guess is that you've been using them with records (or possibly reifying them), but you could just as easily use protocols and (def)types together.
So to me, it seems you've compared apples with oranges here. To help clarify, let me compare apples to apples and oranges to oranges with a couple of different questions:
What problems do protocols solve, and what are the alternatives and their respective advantages/disadvantages?
Protocols let you define functions that operate in different ways on different types. The only other ways to do this are multimethods and simple function logic:
multimethods: have value in being extremely flexible. You can dispatch behavior on type by passing type as the dispatch function, but you can also use any other arbitrary function for dispatching.
internal function logic: You can also (of course) manually check for types in conditionals in your function definitions to decide how to process differently given different types. This is more primitive than multimethod dispatch, and also less extensible. Except in simple cases, multimethods are preferred.
Protocols have the advantage of being much more performant, being based on JVM class/method dispatch, which has been highly optimized. Additionally, protocols were designed to address the expression problem (great read), which makes them really powerful tools for crafting nice, modular, extensible APIs.
What are the advantages/disadvantages of (def)records or reify over (def)types?
On the side of how we specify the structure of data, we have a number of options available:
(def)records: produce a type good for "representing application domain information" (from http://clojure.org/datatypes; worth a read)
(def)types: produce a lighter weight type for creating "artifacts of the implementation/programming domain", such as the standard collection types
reify: construct a one-off object with an anonymous type implementing one or more protocols; good for... one-off things which need to implement a protocol(s)
Practically, records behave like clojure hash-maps, but have the added benefit of being able to implement protocols and have faster attribute lookup. Conveniently, the remain extensible via assoc, though attributes added in this fashion do not share the compiled lookup performance. This is what makes these constructs convenient for implementing applciation logic. Using deftype is advantageous for aspects of implementation/programming domain because they don't implement excess bagage, making the the use cleaner for these cases.
Protocols create interfaces and interfaces are a well, the interface to a type. they describe some aspects of a type though with much less rigor than you would come to expect in a language like Haskell.
machine checking
type inference (you don't get some of your protocols generated from docs of others)
parametric polymorphism (parameterised protocols / protocols with generics don't exist)
higher order protocols (what is the protocol for a function that returns a protocol?)
automatic generation of code / boilerplate
inter-operation with automated tools
Now I'm generally in Java/C# (love both of them, can't really say I'm dedicated to one).
And I've recently been discussing the differences between F# and C# with a friend, when he surprised me saying: "So.. F# sounds a lot like lisp, but with way less 'Swiss-army knife' feel to it."
Now, I was partly ashamed of saying this but I have no idea what lisp was.
After some searching, I saw that lisp is very interesting, but got stumped by the multiple dialects and running environments.
Here is what I know:
I know of 3 dialects:
Common Lisp (I have the Practical Common Lisp book in my bookmarks.
Scheme (a more "theoretical" version of CL)
Clojure. Seems to be a version of CL that runs on JVM.
The basic idea of lisp seems to be about using code as data.
What I want to know:
What is the running environment for different dialects? How do they work/get installed (by this I mean is it a runtime like Java Virtual Machine, or if it requires something else, or if it's supported generally by the OS (as in compiled)). And how to get them (if something is to be gotten)
What is the better dialect to learn (I want the dialect not to be a "learning language" but one you can fully use afterwards without regret of not learning some other one, for example one should first learn C++ before trying out Visual C++, if you know what I mean)
What are the main advantages of lisp in general (I've seen many pages about that saying it's faster in development and execution, but they were all pretty vague about the details)
Can it be generally used for general purpose, or is it concentrated on AI? (By this I mean if, for example, one could make a full console app with it, and then implement OpenGL just as easily and make a game. Learning a language specialized on something precise is worthwhile, but not at the moment for me)
I would also be very happy about any additional details you guys can give me! (Links are appreciated too! E-Books and whatnot.)
Edit: all of the answers here were very useful. As such, I gave them all a +1 to rep, but chose the more concrete one as best. Thank you all.
I also learnt Java and C# intensively before coming to Lisp so hopefully can share some useful perspectives.
Firstly, all Lisps are great and you should definitely consider learning one. There's a famous quote by Eric Raymond:
"Lisp is worth learning for the profound enlightenment experience you
will have when you finally get it; that experience will make you a
better programmer for the rest of your days, even if you never
actually use Lisp itself a lot."
Reasons that Lisps are particularly interesting and powerful are:
Homoiconicity - in Lisp "code is data" - the language itself is written in Lisp data structures. In itself this is interesting, but where it gets really powerful is when you start using this for code generation and advanced macros. Some believe that this features is a key reason why Lisp can help you be more productive than anyone else (short Paul Graham essay)
Interactice development at the REPL - a few other languages also have this, but it is particularly idiomatic and deep-rooted in Lisp culture. It's remarkably productive and liberating to develop while altering a live running program. Recent examples that caught my eye include music hacking with overtone and editing a live game simulation.
Dynamic typing - opinion is more divide on whether this is an advantage or not (I'm personally neutral) but many people thing that dynamically typed langauges give you a productivity advantage, at least in terms of building things quickly. YMMV.
My personal recommendation for a Lisp to learn nowadays would be Clojure. Clojure has a few distinct advantages that make it stand out:
Modern language design - Clojure "refines" Lisp in a number of ways. For example, Clojure adds some new syntax for vectors [] and hashmaps {} in addition to lists (). Purists may disapprove, but I personally believe these find of innovations make the language much nicer to use and read.
Functional first and foremost - all the Lisps are good as functional languages, however Clojure takes it much further. All the standard library is written in terms of pure functions. All data structures are immutable. Mutable state is strictly limited. Lazy sequences (including infinite sequences) are supported. In some senses it feels a bit more like Haskell than the other Lisps.
Concurrency - Clojure has a unique approach to managing concurrency, supported by a very good STM implementation. Worth watching this excellent video for a much deeper explanation.
Runs on the JVM - whatever you think of Java, the JVM is a great platform with extremely good GC, JIT compilation, cross platform portability etc. This can be a barrier to entry for some, but anyone used to Java or C# should quickly feel at home.
Library ecosystem - since Clojure runs on the JVM, it can use Java libraries extremely easily. Calling a Java API from Clojure is trivial - it's just like any other function call with a syntax of (.methodName someObject arg1 arg2). With the availability of the huge Java library ecosystem (mostly open source) Clojure basically leapfrogs all the "niche" languages in terms of practical usefulness
In terms of applications, Clojure is designed to be a fully general purpose langauge so can be used in any field - certainly not limited to AI. I know of people using it in startups, using it for big data processing, even writing games.
Finally on the performance point: you are basically always going to pay a slight performance penalty for using higher level language constructs. However Clojure in my experience is "close enough" to Java or C# that you won't notice the difference for general purpose development. It helps that Clojure is always compiled and that you can use optional type hints to get the performance benefits of static typing.
The flawed benchmarks (as of early 2012) put Clojure within a factor of 2-3 of the speed of statically typed languages like Java, Scala and C#, a little bit behind Common Lisp and a little bit ahead of Scheme (Racket).
Lisp, as you've discovered, is not one language; it's a family of languages that have certain features in common.
There are two primary dialects of Lisp: Common Lisp and Scheme. Each of those two dialects has many implementations, each with their own features. However, both Common Lisp and Scheme are standardized, and the standards define a certain baseline of features which you can expect any implementation to have.
Scheme is a minimalistic language with a very small standard library. It is used primarily by students and theoreticians. Common Lisp has many more language features and a much larger standard library, including a powerful object system, and has been used in large production systems.
Clojure is another minor, more recent dialect. If you want to understand Lisp, you're better off first learning either Common Lisp or Scheme.
My recommendation is to learn Scheme first; it's a purer expression of the ideas that Lisp is made of, and will help you understand the essence of the language. In many ways, Lisp is completely different from Java and other imperative languages; however, what you learn from it will make you a better programmer in those languages. You can easily learn Common Lisp after you know Scheme.
The advantage of Lisp is, simply put, that it's more powerful than other languages. All Lisp code is Lisp data and can be manipulated as such; this allows you to do really cool things with metaprogramming that simply can't be done in other languages, because they don't give you direct access to the data structures that comprise your code. (The reason Lisp can do this and they can't is intimately related to its strange-looking syntax. Every compiler or interpreter, after reading the source code, must translate it into abstract syntax trees. Unlike other languages, Lisp's syntax is a direct representation of the ASTs that Lisp code is translated into, so you know what those trees look like and can manipulate them directly.) The most commonly used metaprogramming feature is macros; Lisp macros can literally translate a bit of source code into anything you can program. You can't do that with, say, C macros.
The "faster in development and execution" thing may have been a reference to one specific feature which most Lisp implementations provide: the read-eval-print loop. You can type an expression into a prompt and the interpreter will evaluate it and print the result. This is wonderful both for learning the language and for debugging or otherwise investigating code.
Lisp is dynamically typed (though statically typed flavors do exist). Most implementations of Lisp run on their own virtual machine; however, many can also be compiled to machine code. Clojure was written specifically to target the JVM; it can also target .NET and JavaScript.
Though originally created for AI research, Lisp is by no means exclusively for AI. The main reason why it's not more popular in mainstream production environments (apart from the self-perpetuating dominance of Java and C#) is library support. Common Lisp has many good libraries out there (Scheme less so), but it pales in comparison to the vast amount of library support available for Java or Python.
If you want to get started, I recommend downloading Racket, a highly popular implementation of Scheme. It has everything you need, including a simple-but-very-powerful IDE with a read-eval-print loop, right out of the box. Though originally developed as a teaching language, it comes with a very large standard library more characteristic of Common Lisp than of Scheme. As a result, it's seeing use in real production environments.
Runtime Environments
Common Lisp and Scheme generally have their own unique runtime environments. There are some variants of Scheme (Chicken and Gambit) which can be translated to C and then linked with their environments so as to be able to be deployed as stand alone executable programs. Clojure runs in the JVM, and there is also a CLR port, but its not clear to me that the CLR port is current with the JVM. Clojure also has Clojurescript, which targets a Javascript runtime.
Which is Better to Learn First
I don't think that question has a good answer. Its up to you. Although if you have experience with the JVM, Clojure might be a bit smoother to start with.
What is Better about Lisp
That's a question liable to start a flame war. I don't have much lisp experience. I started learning Clojure a few months ago in earnest, have looked at Common Lisp and Scheme on and off over the years.
What I like is their dynamic natures. You need to change a function at runtime while your program is running? No problem! Like any power tool, you have to be careful not to chop your bits off when using this.
The power and expressiveness is addicting too. I am able to do some things with little effort that I know I could not achieve in Java, or I know would require a lot more work. Specifically, I was able to put together a description of a data structure - and though the use of macros, delay evaluation of parts of the data until the right time. If I had done that in Java, I would not have been able to nest the declarations like I did because they would have evaluated in the wrong order. Pain would have ensued.
I also like Clojure's view of functional programming, although I have to say it requires work to adjust.
Is Lisp General Purpose
Yes.
--
Mark Volkman has a really good article on Clojure. Many basics are there. One thing that I did in the beginning was to just fire up a repl and experiment when I needed to figure something out programmatically. e.g. explore an API or do some calculations. After a short period of time with that I started working on more building up levels of effort, and I have a project that I'm working on right now that involves Clojure.
There isn't a bad book about Clojure that has been written. The Stuart Sierra book is being updated; and the Oreilly book is about to come out soon, so you might want to wait. The Joy of Clojure is good, but I don't think its a good starter book.
For Common Lisp, I highly recommend the Land of Lisp.
For Scheme, there are several classics including The Little Schemer and SICP.
Oh, and this: http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey (maybe one of the most important talks you'll ever watch), and this http://www.infoq.com/presentations/hickey-clojure (IIRC, really good intro to Clojure).
common lisp
Common Lisp is both compiled and interpreted. Deployments (in Windows) can be done by an exe with DLLs. Or by a precompiled bytecode. Or by installing a Lisp system on the target device and executing the source against it.
Common Lisp is a fully usable industrial language with an active community and libraries for many different tasks.
Lisps are generally faster for development and due to the abstraction capabilities, better at developing higher level concepts. It's hard to explain. Ruby vs. C is an example of this sort of thing. All Lisps carry this capacity IMO.
Common Lisp is a general purpose language. I don't know offhand if modern Common Lisp implementations directly support executing assembly, so it may be difficult to write drivers or use compiler-unsupported CPU instructions.
I like Common Lisp, but Clojure and Racket are not to be sneezed at either. Clojure in particular represents a very interesting track, in my opinion.
For e-books, you can get On Lisp by Graham and Gentle Introduction to Symbolic Computation. Possibly others but those are the ones I can recall.
Other than lack of documentation, what is the difference between definterface and defprotocol in Clojure?
According to the Joy of Clojure:
The advantages of using definterface over defprotocol are restricted
entirely to the fact that the former allows primitive types for
arguments and returns. At some point in the future, the same advantage
will likely be extended to the interfaces generated [by protocols], so use
definterface sparingly and prefer protocols unless absolutely
necessary.
My possibly incomplete understanding was definterface produces an interface .class that java code can implement in order to create classes suitable to pass to your Clojure functions.
Protocols are, in short, a faster and more focused way of doing dispatch than multimethods. you actually have running code in a protocol that is used by other clojure code.
Both seem to be good for building extensible API's and code generation.
What are the main differences between them?
What do you see as their strengths, weaknesses, ...
Disclaimer: I'm more familiar with Clojure than Tcl so apoligies to any Tclers if I misrepresent anything. However here are some points I'm generally aware of:
Both are extremely flexible - you can use meta-programming to generate and execute pretty much any code you like at runtime.
Clojure is a JVM language whereas Tcl is relatively standalone.
Advantages of being on the JVM include being able to generate interoperable code for and act as a DSL for libraries in other JVM languages like Java and Scala. Also you get access to the huge range of Java libraries.
Disadvantage of being on the JVM is relatively substantial start-up time. So you'd probably prefer Clojure for longer-running server applications rather than command line tools that need to execute quickly.
Clojure metaprogramming will get compiled to native code (via JIT in the JVM). Will depend on your application, but I expect this will perform faster than Tcl in most circumstances
Both languages are dynamic (a good thing for metaprogramming on average!) and support functional programming
Clojure contains some interesting abstractions that are very useful for metaprogramming - in particular the considerable in-language support for sequences
I personally find the simlicity of Lisp syntax to be a great advantage for metaprogramming - it's much easier to generate code when there is only one syntactical construct (the s-expression) to worry about...
On average both languages are great for metaprogramming, but if I was choosing between the two:
I'd choose Clojure if I was building a server-side application or if I had a particular need for JVM interoperability
I'd choose Tcl if I wanted a DSL for managing scripts / tools at the command line
I think mikera's answer is excellent.
I would add only that where in clojure metaprogramming tends to focus on macros, a grand unified metaprogramming solution without peer, tcl has several small sharp tools available for metaprogramming, among them the "unknown" command, which can be used to do all sorts of nifty tricks. Also interesting is that even though clojure has only a small number of keywords or "special forms", tcl actually has none, which sort of makes tcl it's own dsl, and changing (or extending) the behavior of any command is possible.
One thing i have to disagree with from mikera's answer is the part about clojure's syntax being more amenable to metaprogramming. One of the unpleasant surprises for me when coming to clojure is actually how much syntactic variation there is in clojure, with the various uses of () [] {} "" ^{} #' :key ... and on and on. I totally grok the justification of this type of syntactic sugar, but i actually find tcl's syntax easier to deal with for "ham-handed" metaprogramming and code generation. And tcl's "everything is a string" nature adds to the simplicity.
As for mulit-processing capabilities, immutable data structures, purely functional nature and many other instances of clojure's distinctives, there really is nothing comparable in tcl.
I couldn't agree more with mikera's conclusion.