Author Topic: DIY programming language  (Read 82354 times)

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: DIY programming language
« Reply #15 on: July 25, 2016, 01:56:27 PM »
If you think that CL is like any other programming language you are factually wrong.

Please do tell what is so different about it.

Antsan

  • Rogueliker
  • ***
  • Posts: 52
  • Karma: +0/-0
    • View Profile
Re: DIY programming language
« Reply #16 on: July 25, 2016, 02:54:49 PM »
I'd really like t know what you were reading, that would give me some idea what you might already know.

And given by your behavior up to this point I'd wager everything I could show you would either be not impressing enough or too complex for you to understand in a timespan that you'd consider worthwhile. I mean, how much time have you spent with Common Lisp before dismissing it? Half an hour? Cannot be more than that if you haven't even found out about macros yet.

But just for you, here's a demonstration of some stuff that is possible in Lisps. If you don't understand what's going on here I'd advise searching out some actual tutorials on Lisp, like, I don't know, Practical Common Lisp or this sample chapter from Land of Lisp or if you want to dive into the more unusual stuff straight away because properly understanding a language is for babies, you can read On Lisp, which is all about macros. I'd also recommend buying "Let Over Lambda", but I assume making such an investment isn't really useful for someone with the patience of a cat.


Let's start with something trivial.
When looking something up in a collection oftentimes you get either back the object you were looking for, or a "NIL" value. This normally looks like this in code:
Code: [Select]
(let ((targeted-monster (find-occupant square)))
  (if targeted-monster
      (hurt targeted-monster)
      (message "There's no target at this point!")))
It's not really that much, but after a while it gets tedious to do that all the time. So I'll write a macro to do it for me:
Code: [Select]
(defmacro [a]if (test then &optional else)
  `(let ((it ,test))
     (if it
         ,then
         ,else)))
Now I can write code as above like this:
Code: [Select]
([a]if (find-occupant square)
       (hurt it)
       (message "There's no target at this point!"))
That already saves a lot of typing.


But that's trivial. Barely worth talking about.
I don't know whether you know about the difference between eager and lazy evaluation. If you don't, go read up on it.
Most Lisps are eagerly evaluated, especially since Lisps are very decidedly not functional and lazy evaluation tends to behave weirdly when side effects are involved unless special care is taken to avoid these problems.
Still, lazy evaluation can be tremendously useful in parts of a program not relying on side effects. Although Common Lisp does not support lazy evaluation out of the box, you can implement it. There are many ways to do this and I'm going to show you the easiest way of doing it, not the most useful one:
Code: [Select]
(defmacro freeze (&body body)
  `(lambda ()
     ,@body))

(defun force (thunk)
  (if (functionp thunk)
      (funcall thunk)
      thunk))
Those to alone aren't that useful, but more powerful macros can be written atop them to make them more useful:
Code: [Select]
(defmacro let~ ((&rest bindings)
                &body body)
  `(thunk
    (let (,@(mapcar (lambda (binding)
                      `(,(first binding)
                        (force ,(second binding))))
                    bindings))
      ,@body)))
and so on. I've got a more involved library for the whole thing here, which relies on this. That library also implements algebraic data types and pattern matching on those algebraic data types.


Of course that's still small fries. writing some lazy evaluation library is only a few steps above writing a "Hello, world!", even if tons more useful.
I already know you think little of entity-component systems, but I find them to be incredibly useful. There already are some implementations for them on the net, but because they all relied on a central system loop to access them, which is too restrictive for my tastes and provides features I really don't need, so I rolled my own.
Entities themselves are simple objects, and the can be created like this;
Code: [Select]
(entity)
They aren't particularly interesting in themselves. The interesting parts are the components. To define a certain type of component, I can do one of the following:
To define a component with an already existing type:
Code: [Select]
(define-component-type strength (integer 0))
To define a component as a structure type:
Code: [Select]
(define-component-struct inventory ()
  (content (empty-set)
           :type set)
  (capacity 0
            :type (integer 0)))
Components can also depend on other components being present.
And then I can write functions which will only be run on entities in which certain components are present and let them do just nothing on other entities:
Code: [Select]
(define-entity-method distance ((e1 entity location1)
                                (e2 entity location2))
  (max (d (x location1)
          (x location2))
       (d (y location 1)
          (y location2))))

You want the implementation of these things?
Here's a paste. I don't want to make the corresponding repository public yet.
Here's some snippets of stuff not in this file:
Code: [Select]
(defmacro [a]if (test then &body else)
  `(let ((it ,test))
     (if it
         ,then
         (progn
           ,@else))))

(defmacro [a]when (test &body then)
  `([a]if ,test
       (progn
         ,@then)))

(defmacro [av]if (test then &body else)
  (let ((g!found? (gensym "found?")))
    `(multiple-value-bind (it ,g!found?)
         ,test
       (if ,g!found?
           ,then
           (progn
             ,@else)))))

(defmacro [av]when (test &body then)
  `([av]if ,test
       (progn
         ,@then)))

(defun car-or-x (x)
  (if (consp x)
      (car x)
      x))

(defun symb (&rest objs)
  (intern (format nil "~{~A~}"
                  objs)))

(defun ensure-list (x)
  (the list
       (if (listp x)
           x
           (list x))))

(defun plist-rem (indicator/s property-list)
  (declare (type (or cons symbol)
                 indicator/s)
           (type list property-list))
  (the list
       (loop for (prop item)
          on property-list by #'cddr
          unless (if (consp indicator/s)
                     (member prop indicator/s
                             :test #'eq)
                     (eq prop indicator/s))
          nconc
            `(,prop ,item))))

(defun copy-hash-table (hash-table)
  (declare (type hash-table hash-table))
  (the hash-table
       (let ((newhash (make-hash-table :test (hash-table-test hash-table)
                                       :size (hash-table-size hash-table)
                                       :rehash-size
                                       (hash-table-rehash-size hash-table)
                                       :rehash-threshold
                                       (hash-table-rehash-threshold
                                        hash-table))))
         (declare (type hash-table newhash))
         (maphash (lambda (key value)
                    (setf (gethash key newhash)
                          value))
                  hash-table)
         newhash)))


None of this is in Common Lisp by default. Every programming paradigm you can come up with is implementable in Common Lisp itself in such a way that you can write it intermingled with the more typical Common Lisp. Damn, there are libraries implementing Prolog in Common Lisp – that is, you can write Common Lisp and Prolog in the same file without any external tools, without the need to write a Prolog interpreter or compiler. Just load the library and you're good to go.

Even if you're not going to use Common Lisp or any other Lisp for writing your roguelike, a Lisp is still your best bet for writing your own programming language. Once again, I point you at "Let Over Lambda" and "On Lisp".


In the end, unless you are willing to understand what programming actually is, it doesn't matter which programming language you are working in, you're just going to suck at it. And if you're going to write a programming language without any effort on your part to even understand what others have already been doing, your programming language is going to suck, because you'll make errors that others already made decades ago only because you have no idea why programming languages are the way they are.
Breaking stupid rules is a worthy endeavor, sure, but before that you must understand the rules you want to break.
« Last Edit: July 25, 2016, 03:05:14 PM by Antsan »

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: DIY programming language
« Reply #17 on: July 26, 2016, 04:28:08 PM »
In the end, unless you are willing to understand what programming actually is, it doesn't matter which programming language you are working in, you're just going to suck at it.

I don't suck at programming, you do. Apparently we are not even on the same level here, meaning you are operating on everyday mundane level, thinking that examples you gave are interesting or remarkable, which they are not.

Antsan

  • Rogueliker
  • ***
  • Posts: 52
  • Karma: +0/-0
    • View Profile
Re: DIY programming language
« Reply #18 on: July 26, 2016, 04:45:58 PM »
I'm not sure whether you're trying to mask your own ignorance or trolling.

What would you actually want to see in the first place? It's kind of strange that you only give off these fuzzy, non-descriptive blurbs about some nebulous ideas that there may be some interesting concepts to make programming more accessible for non-academics, but finding out what such a language would actually look like doesn't seem to be in your interest. I mean, I'm showing you a tool and you berate me for not doing your work for you?

Of course I'm showing you trivial examples!
« Last Edit: July 26, 2016, 04:49:59 PM by Antsan »

Worthless_Bums

  • Newcomer
  • Posts: 44
  • Karma: +0/-0
    • View Profile
    • Steam Marines - squad based roguelike
    • Email
Re: DIY programming language
« Reply #19 on: July 27, 2016, 09:38:42 AM »
I won't link to it here, but if you take a look at Krice's dev blog you'll get a pretty solid sense of where he's at as a programmer.

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: DIY programming language
« Reply #20 on: July 27, 2016, 10:22:30 AM »
I won't link to it here, but if you take a look at Krice's dev blog you'll get a pretty solid sense of where he's at as a programmer.

I've reached this stage from another way than I guess "normal" programmers. That's why I can see there is something wrong about pretty much all languages, but I can't exactly say what it is. It's usually something different depending on the language.

Antsan

  • Rogueliker
  • ***
  • Posts: 52
  • Karma: +0/-0
    • View Profile
Re: DIY programming language
« Reply #21 on: July 27, 2016, 10:38:58 AM »
I'm currently in July'9. The blog is surprisingly readable this far, but there's already a ton of head-scratching going on. How the heck do you design a map generation algorithm in a way that leads to corridor carving being tightly coupled to the rest of map generation?

Word of advice: Problems don't exist in anything itself but only in the relations between things. That is, not the programming languages are flawed, the relation between you and programming languages is.
Of course you'd have a point if there were problems in all relations between programming languages and humans, but I can assure you that this is not the case.
« Last Edit: July 27, 2016, 10:40:33 AM by Antsan »

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: DIY programming language
« Reply #22 on: July 27, 2016, 11:12:55 AM »
not the programming languages are flawed

I wouldn't say that certain things in languages are "flaws", but in case of C++ many things are a result of C++ being ancient. I was just thinking about how I would improve the type system in C++. Some thoughts:

1. Remove ancient types like short, use one type for everything.
2. No 'char' type needed, only string type(s).
3. 'Range' type for integers with automatic limits.
4. 'Unsigned' type for integers (default is signed).
5. No silent type conversions, only through special keyword (+ built-in conversions from integer to string etc.)
6. Type determined from value, no 'int',  'double' etc. needed unless using range or unsigned keywords.
7. Variables const by default, 'var' for mutable variables.

Antsan

  • Rogueliker
  • ***
  • Posts: 52
  • Karma: +0/-0
    • View Profile
Re: DIY programming language
« Reply #23 on: July 27, 2016, 11:31:55 AM »
That sounds reasonable.

1. Common Lisp has multiple number types, but there is the general type "integer", which is a bignum internally – that is, size of integers is only bounded by memory size.
2. I disagree with this one. Having characters distinct from strings of length one ensures that type checks can be made at compilation time whether setting a single character in a string actually works as intended. What would it mean to set the third character in a string to "foo"?
3. Also in Common Lisp. "(integer -5)" is the type of all integers >=-5. "(integer * 20)" is the type of all integers <=20. "(integer -3000 524)" is the type of all integers x with -3000<=x<=524. Ranges can be made exclusive by wrapping the open bound in parenthesis, like this: "(integer (6))", which is the type of all integers >6. Arbitrary numbers chosen to show that this is not limited to a special subset of numbers.
4. See (3). This also is in C++: Use "unsigned int".
5. I see that this is desirable. When you declare types for variables in Common Lisp, this is enforced. Normally variables don't have types, though, they take just any value you give them. Values themselves still always have types.
6. In C++ you can use the "auto" keyword in place of a specific type. The compiler then infers the type for you. In Common Lisp it's the values that have types, not the variables.
7. Don't know any language that works this way. Haskell is purely functional so mutable variables require a special context either way, but I doubt this is what you want. I hear Clojure is big in immutable structures, but once again this is not about variables being constant but rather the values themselves being immutable. Given that you probably work mostly inside structures and shouldn't tamper around with freely dangling variables that much either way, I think this might be what you're looking for. I have no experience at all with Clojure, though.

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: DIY programming language
« Reply #24 on: July 27, 2016, 01:58:11 PM »
2. Didn't compute.
3. More like range in Ada: range 1..10 means the integer can be only from 1 to 10. Simple, easy, safe.
4.

a=10; //this is signed int (default)
unsigned a=10; //now we know it's unsigned

6. Why have 'auto' at all? Why not just determine the type? a=10; //int, a=1.0; //floating point, a="string"; //string
7. When you become more experinced and data-driven in C++ you are using const a lot. Why not make it the default for data.

8. Also, I think parameters to functions should be references by default. Probably even const references. I don't think there even should be by value parameters in functions.

Lord_Mork

  • Newcomer
  • Posts: 43
  • Karma: +0/-0
    • View Profile
Re: DIY programming language
« Reply #25 on: July 27, 2016, 02:48:01 PM »
I'd recommend Common Lisp (of course)

I guess some of these days I should really try Common Lisp or another language that has ridiculous syntax. Just to see if it's actually possible to write any kind of program. At my age it's.. eh.. common to quit stuff if they look like there is some kind of learning curve or barrier to climb over.

I've written small things in Racket (or Scheme, I have some confusion about the difference), which, as far as I can tell, is a descendant of Lisp. All I can say is that it is a strange language. The syntax is all prefix and very uniform, every single procedure call is ([procedure name] [arguments]), which means that nested loops and conditionals cause crap like this : "))))))))))" to close. Annoying without a good IDE, but that shouldn't be a problem today.

For stranger syntax, assuming you haven't already, maybe look into Cat or Forth? I have heard/read that writing your own "forth style" language is fairly easy
http://www.figuk.plus.com/byof.htm

Antsan

  • Rogueliker
  • ***
  • Posts: 52
  • Karma: +0/-0
    • View Profile
Re: DIY programming language
« Reply #26 on: July 27, 2016, 03:15:07 PM »
Quote
3. More like range in Ada: range 1..10 means the integer can be only from 1 to 10. Simple, easy, safe.
Yep, (integer 0 10) is exactly the same in Common Lisp. There's also (real 0 10), for instance, which would include numbers like 2/7 and 0.734.

Quote
6. Why have 'auto' at all? Why not just determine the type? a=10; //int, a=1.0; //floating point, a="string"; //string
Don't know. To tell the compiler that a new variable is declared, probably.

Quote
I've written small things in Racket (or Scheme, I have some confusion about the difference), which, as far as I can tell, is a descendant of Lisp.
Racket is an implementation of Scheme with various enhancements not in the Scheme standard.
Scheme is a Lisp dialect.
Lisp is not a single language, but a language family. When people say "Lisp" to denote a single language, they probably mean "Common Lisp", although in Lisp circles this is not well-received.

Quote
For stranger syntax, assuming you haven't already, maybe look into Cat or Forth? I have heard/read that writing your own "forth style" language is fairly easy
Forth is awesome. Unfortunately I haven't taken the time to really learn it. I think it's not for Krice, though, since it hasn't types at all – at least as long you don't implement them yourself.

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: DIY programming language
« Reply #27 on: July 28, 2016, 08:44:39 AM »
I just realized that the reason why I'm thinking about a new programming language, along with trying to figure out stuff like prime number theorem and quantum wave function, is that my brain is trying to reach Super Saiyan 2!

Aleksanderus

  • Rogueliker
  • ***
  • Posts: 179
  • Karma: +0/-0
  • Champion of the unknown
    • View Profile
Re: DIY programming language
« Reply #28 on: July 28, 2016, 09:22:09 AM »
I just realized that the reason why I'm thinking about a new programming language, along with trying to figure out stuff like prime number theorem and quantum wave function, is that my brain is trying to reach Super Saiyan 2!
So that's why you see the paterns beyond normal understanding!

I wonder if your brain becomes golden when you are transformed...

mushroom patch

  • Rogueliker
  • ***
  • Posts: 554
  • Karma: +0/-0
    • View Profile
Re: DIY programming language
« Reply #29 on: July 28, 2016, 11:56:08 AM »
I just realized that the reason why I'm thinking about a new programming language, along with trying to figure out stuff like prime number theorem and quantum wave function, is that my brain is trying to reach Super Saiyan 2!

Weird, most people figure this kind of stuff out in college.