Giter VIP home page Giter VIP logo

Comments (28)

VincentToups avatar VincentToups commented on July 17, 2024

This is similar to the plist discussion going on over on the dash.el repository.

I would probably do something like

(defun extract/c (key) (lexical-let ((key key)) (lambda (plist) (plist-get key plist))))

(match '(headline (:raw-value "Jacintha Love" :begin 1 :end 198 :pre-blank 0 :hiddenp nil :contents-begin 17) ...) 
    ((_ (call (extract/c :contents-begin) value)) value))

You can generalize this into a custom plist matcher using defpattern pretty easily:

 (defpattern plist (&rest kp-pairs) 
     `(and ,@(loop for (k v . rest) on kv-pairs collect `(call (extract/c ,k) ,p))))

Of course this is not so performant for large plists. You could coerce the plist into a hash table and do the same thing using hash lookup if you were so concerned.

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

So pretty much do the matching elsewhere?

I really like dash's end of list mechanism by the way:

(a b . c) as opposed to shadchen's (a b (tail c))

So now I'm wondering whether it might be good to take both approaches and combine them.

from shadchen-el.

VincentToups avatar VincentToups commented on July 17, 2024

The more idiomatic match for the tail of a list is list* in accord with the function of the same name. You cannot, unfortunately, use . unless all you want to do is match against a symbol, because syntactically (list a b . (and stringp s)) is read by the reader as(list a b and stringp s). There is no way, post-read-time, to know whether the denotation was intending the last form to be a sub-pattern or a simple list of symbols.

One could forbid the use of symbols denoting patterns in match expressions and correctly interpret (list a b and stringp s) but this doesn't seem like a good solution.

With the plist defpattern defined above, you can match against a plist pretty idiomatically:

(match '(:a 'a :b 'b)
((plist :a (and symbolp x)) (message "matched a symbol at key :a" x)))

The point of extensibility in Shadchen is that any match semantics you might want for custom objects can be given a concise form which hides the details of the pattern match.

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

Ah, right. Gotcha.

But it would be nice if those things were all there. plist and alist matching out of the box would be fantastic.

Ah well, perhaps I'll have a play and send you some PRs.

from shadchen-el.

VincentToups avatar VincentToups commented on July 17, 2024

By the way, I am an enormous fan of you emacs work. I definitely recognize a kindred spirit re making emacs do insane things. You are inspiring me to brush off some of my old projects!

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

Awww. Shucks. I just wish I understood your code. I can't possibly hope to keep up with you.

from shadchen-el.

VincentToups avatar VincentToups commented on July 17, 2024

If you can't understand my code, it is definitely my problem, not yours. I would welcome pull requests and I am in particular interested in modernizing shadchen el a bit. I sort of delayed moving to Emacs 24 for quite a long time, for various reasons, and as such it is kind of ugly or at least old looking, I would guess.

Plus, I am a bit embarrassed, as I've said before, about the quality of the code here, so I kind of stopped promoting Shadchen when I realized there was a lot for me to learn about software engineering. I would be nice to go back and clean it up. Thanks for giving me the reminder to do so.

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

I don't think you need to clear it up. If I could give you any advice it would be "if it works, ship it".

I am torn between this and -let. -let is really nice but this is more powerful in the end. I'll get this added to marmalade and then I'll try and send you PRs.

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

So:

(defun extract/c (key)
  (lambda (plist)
    (plist-get key plist)))

(defpattern plist (&rest kv-pairs) 
  `(and ,@(loop for (k v . rest) on kv-pairs
             collect
               `(funcall (extract/c ,k) ,v))))

(match
 '(:one 1 :two 2 :three 3)
 ((plist :two a) a)) => nil

what am I doing wrong?

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

Aha. The definition of extract/c was wrong:

(defun extract/c (key)
  (lambda (plist)
    (plist-get plist key)))

(defpattern plist (&rest kv-pairs) 
  `(and ,@(loop for (k v . rest) on kv-pairs
             collect
               `(funcall (extract/c ,k) ,v))))

(match
 '(:one 1 :two 2 :three 3)
 ((plist :two a) a))

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

... and alists too:

(defun extract/a (key)
  (lambda (alist) (cdr-safe (assoc key alist))))

(defpattern alist (&rest kv-pairs)
  (cl-labels ((alist-get (key)
                         (lambda (alist)
                           (cdr (assoc key alist)))))
    `(and ,@(loop for (k v . rest) on kv-pairs
               collect
                 `(funcall (extract/a ,k) ,v)))))

(match
 '((a . 1)(b . 2)(c . 3))
 ((alist 'c a) a))

I wonder how many other types could be provided for. Windows? Frames?

One other thing about this lib is that it seems like it's a straight port from your CL version. I found a few doc nits but the doc looks the same between the two. Can I submit PRs to this? or do you generate one from the other?

from shadchen-el.

VincentToups avatar VincentToups commented on July 17, 2024

Nice work! But I think we also need a by #'cddr on the loop in the pattern
expansion of the plist macro (it was my mistake).

I wish I generated one from the other, but they are divergent enough that
it's not so easy. Plus, there are many great matches in Common Lisp and
fewer in Emacs, so the el version got more of my attention.

What advice can you give me about how people are doing testing in Emacs
Lisp these days? I'd like to build a test suite.
On Oct 8, 2014 1:16 AM, "Nic Ferrier" [email protected] wrote:

... and alists too:

(defun extract/a (key)
(lambda (alist) (cdr-safe (assoc key alist))))

(defpattern alist (&rest kv-pairs)
(cl-labels ((alist-get (key)
(lambda (alist)
(cdr (assoc key alist)))))
(and ,@(loop for (k v . rest) on kv-pairs collect (funcall (extract/a ,k) ,v)))))

(match
'((a . 1)(b . 2)(c . 3))
((alist 'c a) a))

I wonder how many other types could be provided for. Windows? Frames?

One other thing about this lib is that it seems like it's a straight port
from your CL version. I found a few doc nits but the doc looks the same
between the two. Can I submit PRs to this? or do you generate one from the
other?


Reply to this email directly or view it on GitHub
#4 (comment)
.

from shadchen-el.

VincentToups avatar VincentToups commented on July 17, 2024

Now that I am at a real computer, I can test these things out. We want something that looks like this:

(defun extract/c (key)
  (lexical-let ((key key))
      (lambda (plist)
        (plist-get plist key))))

(defpattern plist (&rest kv-pairs) 
  `(and ,@(loop for (k v . rest) on kv-pairs by #'cddr
                collect
                `(funcall (extract/c ,k) ,v))))


(match (list :x 10 :y 11 :z 12)
       ((plist :x x :y y) (list x y)))

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

Great! I'll send a pr on that.

Personally for testing I use ert which is built in, it works pretty well, I see no reason to use anything else.

I have built my own continuous integration stuff for that using a tool I call elpakit. Other people use cask for the same task.

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

I'll take a look at this myself I guess... but to what extent could match be a macro? then one could debug the evaluated forms.

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

You were asking about tests. A complex set of tests is here:

https://github.com/joddie/macrostep/blob/master/macrostep-test.el

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

Is the inspiration for shadchen the matcher in racket? It seems so. If so I'll try to use that as inspiration for any extra patterns I define?

I'd like to add the ___ to the list matcher for example.

from shadchen-el.

VincentToups avatar VincentToups commented on July 17, 2024

It is definitely based on Racket's pattern matcher. I will have to refresh my memory on the ___ pattern.

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

It's something that let's you match many things:

(match (list 1 2 3 4 5 6)
  ((list 1 ___ (tail a)) a))) => 6

from shadchen-el.

VincentToups avatar VincentToups commented on July 17, 2024

That should probably be (6) rather than 6. Tail performs a pattern match
on the remainder of the list not matched by the previous patterns.

The append pattern does something like this already.

(append ... ) produces the first match
satisfying all the list patterns (there may, in general, be many). Append
has a crazy performance profile because it has to back track and sometimes
blows the stack, though, so it might be better to have a separate pattern.
You would write something like this:

(append (list 1)
(___)
(list last))

And I would expect this pattern to match last to 6 if used against the
value in your example.

If you want to take a crack at making append better behaved, that might be
my ideal way forward.

On Mon, Oct 13, 2014 at 11:06 PM, Nic Ferrier [email protected]
wrote:

It's something that let's you match many things:

(match (list 1 2 3 4 5 6)
((list 1 ___ (tail a)) a))) => 6


Reply to this email directly or view it on GitHub
#4 (comment)
.

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

Hum. Ok. I'll look.

Slightly related - how about declaring a specific index for the macros?

(match  value
  (matches...))

eg:

(defmacro ...
   (declare (indent 1) ...)  ...)

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

Yeah, so further to your comment, this works:

(match
 (number-sequence 1 10)
 ((append (list 1) _ (list y)) y))  => 10

from shadchen-el.

VincentToups avatar VincentToups commented on July 17, 2024

I think its worth looking into the implementation, because it might be sort
of wacky.

I don't object to putting in a (___) pattern which is active just inside of
list matches for that specific case, if it is pretty common. Adding indent
declarations is a great idea, by the way. Thanks for taking so much time
to improve shadchen!

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

I definitely will look into the implementation. Particularly if I can
find a problem that causes it to be a pain.

[email protected] writes:

I think its worth looking into the implementation, because it might be sort
of wacky.

I don't object to putting in a (___) pattern which is active just inside of
list matches for that specific case, if it is pretty common. Adding indent
declarations is a great idea, by the way. Thanks for taking so much time
to improve shadchen!


Reply to this email directly or view it on GitHub:
#4 (comment)

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

Bizarrely when I come to use it again it doesn't work! weird!

from shadchen-el.

VincentToups avatar VincentToups commented on July 17, 2024

What doesn't?

On Wed, Oct 29, 2014 at 8:56 PM, Nic Ferrier [email protected]
wrote:

Bizarrely when I come to use it again it doesn't work! weird!


Reply to this email directly or view it on GitHub
#4 (comment)
.

from shadchen-el.

nicferrier avatar nicferrier commented on July 17, 2024

The append. I need to add a test I guess.

from shadchen-el.

VincentToups avatar VincentToups commented on July 17, 2024

It is a kind of tricky thing, concat and append. I have often thought
about removing them. Super handy, but also kind of "stupid programming
tricks". Using Shadchen and a few macros one can easily write a really
nice monadic parsing framework that handles this sort of thing much more
efficiently. So I don't know.

I think making concat and append efficient (or just one, as concat can be
implemented in terms of append) would be neat little project in writing a
performant back tracker in Emacs Lisp.

-V

On Wed, Oct 29, 2014 at 10:40 PM, Nic Ferrier [email protected]
wrote:

The append. I need to add a test I guess.


Reply to this email directly or view it on GitHub
#4 (comment)
.

from shadchen-el.

Related Issues (7)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.