Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ets-ms is attempting to match 'undefined' when using match-record with unspecified slots #466

Closed
dendrown opened this issue Feb 14, 2023 · 5 comments

Comments

@dendrown
Copy link

Hello. When using the match-record macro within an ets-ms expression, the resulting match specification includes the default undefined atom for any record slots not explicitly specified. To use an example from Learn Yourself some Erlang for Great Good:

lfe> (defrecord food name calories price group)
set-food-group

lfe> (ets-ms (((match-food name name calories c)) (when (< c 600)) name))
(#(#(food $1 $2 undefined undefined) (#(< $2 600)) ($1)))

Explicitly adding "don't cares" will give us what we need; however, I don't believe this is supposed to be necessary:

lfe> (ets-ms (((match-food name name price _ group _ calories c)) (when (< c 600)) name))
(#(#(food $1 $2 _ _) (#(< $2 600)) ($1)))
@dendrown
Copy link
Author

I thought this problem might be related to issue #446, but I am still seeing as of the current version on the "develop" branch: 9a75089 [ Wed Jan 18 ].

@rvirding
Copy link
Member

Yes, this is a known problem, sort of. It has been caused by how the LFE compiler interfaces the Erlang compiler. It now pushed much more work to the Erlang compiler and gets all of the optimisations the Erlang compiler does, which is a lot. The downside was the handling of records inside the ets-ms macro. I hadn't noticed it as i very seldom use it.

I am looking at a simple work-around and will get if it works.

@rvirding
Copy link
Member

rvirding commented Feb 24, 2023

@dendrown A work-around to this is to do it the "erlang way" and use the function ets:fun2ms and include the file "stdlib/include/ms_transform.hrl". This seems to work.

(defmodule ms
  (export (f1 1))
  )

(include-lib "stdlib/include/ms_transform.hrl")

(defrecord sune
  (a 42)
  (b)
  (c (date))
  (d))

(defun f1 (v1)
  (list
   (ets:fun2ms (match-lambda
		 ([(record sune a av b 99 c c)] (tuple c v1))))
   (ets:fun2ms (match-lambda
		 ([(record sune a v1)] (record sune d v1))))))

I may need to improve the handling of include-lib a bit but it works.

@dendrown
Copy link
Author

Thanks, @rvirding. It's always good to know there's a work-around,

@rvirding
Copy link
Member

rvirding commented Apr 10, 2023

This has now been fixed in two commits, b41b339 and 0717b8f, in the develop branch. I will soon make a new version in the main branch with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants