wowpatrick
wowpatrick

Reputation: 5180

What is define-struct in Racket and why are there no variables?

In one of my CS courses at university we have to work with Racket. Most of my programming time before university I spent with PHP and Java and also JavaScript. I know Racket is a functional programming language, just like JavaScript (Edit: Of course it isn't. But I felt like I was doing 'functional' programming with it, which after seeing the answers, is a wrong perception.) But I still don't understand some fundamental characteristics of Racket (Scheme).

  1. Why are there no 'real' variables? Why is everything a function in Racket/Scheme? Why did the language designers not include them?

  2. What is define-struct? Is it a function? Is it a class? I somehow, because of my PHP background, always think it's a class, but that can't be really correct.

My question here is I want to understand the concept of the language. I personally still think it's really strange and not like anything I worked with before, so my brain tries to compare it with JavaScript, but it just seems so different to me. Parallels/differences to JavaScript would help a lot!

Upvotes: 6

Views: 13344

Answers (4)

Racket Noob
Racket Noob

Reputation: 1066

  1. There are 'real' variables in Racket. For example, if you write this code

    (define x 3)
    

    the 'global' variable x will be set to value 3. If you now write

    (set! x 4)
    

    the variable x will change its value to 4. So, in Racket you can have a 'normal' variables like in any 'normal' language, if you want. The fact is that in Racket the preferred programming style is functional as opposed to procedural. In functional programming style variable mutation is discouraged.

  2. define-struct is a Racket macro that you use to define 'structure template' along with several other things. For example, if you write:

    (define-struct coord (x y))
    

    you just defined a 'structure template' (i.e user type named coord that have two "slots": x and y). After that, you can now:

    • create new "instance" of structure coord, for example like this: (make-coord 2 3)

    • extract slot value from the structure object:

      (coord-x (make-coord 2 3)) ;will return 2
      

      or

      (coord-y (make-coord 2 3)) ;will return 3
      
    • you can ask if some given object is just that structure. For example, (coord? 3) will return #f, since 3 is not of type coord structure, but

      (coord? (make-coord 2 3)) ;will return #t
      

Upvotes: 24

Greg Hendershott
Greg Hendershott

Reputation: 16260

Perhaps the most popular or in-fashion way to program (using languages like C++, Javascript, and Java) has a few characteristics. You may take them for granted as self-evident, the only possible way. They include:

  • Imperative

You focus on saying "do this step, then this next step" and so on.

  • Using mutation.

You declare a variable, and keep assigning it different values ("mutate it").

  • Object-oriented.

You bundle code and data into classes, and declare instances of them as objects. Then you mutate the objects.

Learning Scheme or Racket will help you understand that these aren't the only way to go about it.

It might make your brain hurt at first, in the same way that a philosophy class might cause you to question things you took for granted. However unlike the philosophy class, there will be some practical pay-off to making brain hurt. :)

An alternative:

  • Functional (instead of imperative). Focus on expressions that return values, instead of making to-do lists of steps.
  • Immutable. Ditto.
  • Not object oriented. Using objects of classes can be a good approach to some problems, but not all. If you want to bundle code with data, there are some more general ways to go about it, such as closures with "let over lambda" and so on. Sometimes you don't need all the "baggage" of classes and especially inheritance.

Scheme and Racket make it easy to explore these ideas. But they are not "pure functional" like say Haskell, so if you really want to do imperative, mutable, object-oriented things you can do that, too. However there's not much point in learning Racket to do things the same way you would in Javascript.

Upvotes: 8

Fred Foo
Fred Foo

Reputation: 363597

  1. There are variables in Scheme.

    > (define a 1)
    #<unspecified>
    > a
    1
    > (set! a 2)
    #<unspecified>
    > a
    2
    

    There are even mutable data structures in this language.

    > (begin
    >   (define v (make-vector 4))
    >   (vector-set! v 0 'foo)
    >   (vector-set! v 1 'bar)
    >   (vector-set! v 2 'baz)
    >   (vector-set! v 3 'quux))
    #<unspecified>
    > v
    #(foo bar baz quux)
    

    Scheme is not a pure FP language; it does allow imperative programming, although it is mostly geared towards functional programming. That's a design choice that Scheme's inventors made.

  2. define-struct is a special form; it's syntax, like the function or return keywords in JavaScript.

Upvotes: 2

Taymon
Taymon

Reputation: 25676

Scheme very much has "real" variables.

The difference between a functional language (like Racket) and an imperative language (like JavaScript or PHP) is that in a functional language, you usually don't use mutable state. Variables are better thought of as names for values than as containers that can hold values. Instead of using things like looping constructs to change values in variables, you instead use recursion for flow control.

define-struct is a special syntactic form, kind of like keywords in other languages. (Unlike other languages, in Scheme you can create your own syntactic forms.) It defines a struct type, which is like a class but doesn't have methods. It also defines a number of functions that help you utilize your new struct type.

Upvotes: 5

Related Questions