Data structures in Rascal - rascal

I am looking for a data structure that can mimic an Object or a struct. Really, just some compact way to pass around different types of variables. Currently I am using a tuple but referencing various parts of the tuple is less pleasant than I would like. Currently I've just created aliases that represent the various locations in the tuple:
alias AuxClass = tuple[str,str,list[int],list[int],Dec];
int ACLS = 0;
But I've had to restructure this tuple and thus had to change the indexing. Is there something I can use here that I've missed or perhaps a feature coming in the future?
Thanks!

Please take a look at the algebraic data types feature:
http://tutor.rascal-mpl.org/Rascal/Rascal.html#/Rascal/Declarations/AlgebraicDataType/AlgebraicDataType.html
You can create a constructor to represent the type of data that you are trying to define above, similar to what you would do with a struct, and give each element in the constructor a field name:
data AuxClass = auxClass(str f1, str f2, list[int] f3, list[int] f4, Dec f5)
You can then create new instances of this just using the constructor name and providing the data:
a = auxClass("Hello", "World", [1,2,3], [4,5,6], D1) (where D1 is a Dec).
Once you have an instance, you can access information using the field names:
a.f1 // which equals "Hello"
a.f3 // which equals [1,2,3]
size(a.f3) // which currently equals 3
and you can update information using the field names:
a.f2 = "Rascal"
a.f4 = a.f4 + 7 // f4 is now [4,5,6,7]
Algebraic data types are actually quite flexible, so there is a lot you can do with them beyond this. Feel free to look through the documentation and ask questions here.

Related

Lua: Sort table of numbers with multiple dots

I have a table of strings like this:
{
"1",
"1.5",
"3.13",
"1.2.5.7",
"2.5",
"1.3.5",
"2.2.5.7.10",
"1.17",
"1.10.5",
"2.3.14.9",
"3.5.21.9.3",
"4"
}
And would like to sort that like this:
{
"1",
"1.2.5.7",
"1.3.5",
"1.5",
"1.10.5",
"1.17",
"2.2.5.7.10",
"2.3.14.9",
"2.5",
"3.5.21.9.3",
"3.13",
"4"
}
How do I sort this in Lua? I know that table.sort() will be used, I just don't know the function (second parameter) to use for comparison.
Given your requirements, you probably want something like natural sort order. I described several possible solution as well as their impact on the results in a blog post.
The simplest solution may look like this (below), but there are 5 different solutions listed with different complexity and the results:
function alphanumsort(o)
local function padnum(d) return ("%03d%s"):format(#d, d) end
table.sort(o, function(a,b)
return tostring(a):gsub("%d+",padnum) < tostring(b):gsub("%d+",padnum) end)
return o
end
table.sort sorts ascending by default. You don't have to provide a second parameter then. As you're sorting strings Lua will compare the strings character by character. Hence you must implement a sorting function that tells Lua which comes first.
I just don't know the function (second parameter) to use for
comparison.
That's why people wrote the Lua Reference Manual
table.sort (list [, comp])
Sorts the list elements in a given order, in-place, from list1 to
list[#list]. If comp is given, then it must be a function that
receives two list elements and returns true when the first element
must come before the second in the final order, so that, after the
sort, i <= j implies not comp(list[j],list[i]). If comp is not given,
then the standard Lua operator < is used instead.
The comp function must define a consistent order; more formally, the
function must define a strict weak order. (A weak order is similar to
a total order, but it can equate different elements for comparison
purposes.)
The sort algorithm is not stable: Different elements considered equal
by the given order may have their relative positions changed by the
sort.
Think about how you would do it with pen an paper. You would compare each number segment. As soon as a segment is smaller than the other you know this number comes first.
So a solution would probably require you to get those segments for the strings, convert them to numbers so you can compare their values...

What exactly does table.move do, and when would I use it?

The reference manual has this to say about the table.move function, introduced in Lua 5.3:
table.move (a1, f, e, t [,a2])
Moves elements from table a1 to table a2, performing the equivalent to the following multiple assignment: a2[t],··· = a1[f],···,a1[e]. The default for a2 is a1. The destination range can overlap with the source range. The number of elements to be moved must fit in a Lua integer.
This description leaves a lot to be desired. I'm hoping for a general, canonical explanation of the function that goes into more detail than the reference manual. (Oddly, I could not find such an explanation anywhere on the web, perhaps because the function is fairly new.)
Particular points I am still confused on after reading the reference manual's explanation a few times:
When it says "move", that means the items are being removed from their original location, correct? Do the indices of items above the removed items shift down to fill the gaps? If so, and we're moving within the same table, does t point to the original location before anything starts moving?
Is there some significance to the choice of index letters f, e, and t?
There is no similar function in any other language I know. What's an example of how I might use this? Since it's one of only seven table functions, I presume it's quite useful.
Moves elements from table a1 to table a2, performing the equivalent to the following multiple assignment a2[t],··· = a1[f],···,a1[e]
Maybe they could have added the information this is done using consecutive integer values from f to e.
If you know Lua a bit more you'll know that a Lua table has no order. So the only way to make that code work is to use consecutive integer keys. Especially as the documentation mentions a source range.
Giving the equivalent syntax is the most unambiguous way of describing a function.
If you know the very basic concept of multiple assignment in Lua (see 3.3.3. Assignment) , you know what this function does.
table.move(a1, 1, 4, 6, a2) would copy a1[1], a1[2], a1[3], a1[4] into a2[6], a2[7], a2[8], a2[9]
The most common usecase is probably to get a subset of a list.
local values = {1,45,1,44,123,2354,321,745,1231}
old syntax:
local subset = {}
for i = 3, 7 do
table.insert(subset, values[i])
end
new:
local subset = table.move(values, 5, 7, 1, {})
Or maybe you quickly want to remove the last 3 values from a table?
local a = {1,2,3,4,5,6,7}
table.move({}, 1,3,#a-2, a)

Ordering items by sizename when it's not alphabetically logic?

In my app, the admin may add sizes to his products in this order.
Variant.create(size_name: "L")
Variant.create(size_name: "S")
Variant.create(size_name: "XXL")
Variant.create(size_name: "XL")
Sizes could also be (30,24, 33, 31, 29)
In my product view, the select tag display in the order it has been created.
I would like to sort from the smallest size to the biggest (S, M, L ...).
With the numerically sizes,I can order from the smallest to the biggest it's Okay
How I am supped to make sure that both sizes (the numerically and the alphabetically) could be sorted from the smallest to the biggest?
There are many ways to solve this, but at the core of any solution you need to define the order manually (or use a third party library which has already written this manual ordering for you?).
For example, you could somewhere define e.g.
SIZE_NAMES = %w[XS S M L XL XXL]
and then elsewhere in the code, use something like:
variants.sort_by { |variant| SIZE_NAMES.index(variant.size) }
For a more "advanced" solution, you could instead consider defining each size as a custom object rather than a regular String. Take a look at the Comparable module, and the <=> ("spaceship") operator.
By utilising this, you could potentially implement it in such a way that e.g. variants.sort will automatically compare variants by their "converted" size, and order them as you expect.
If you wish to do sorting on db side then you have two options:
Predefined sort like so:
Variant.order(
"CASE size_name
WHEN 'S' THEN 1
WHEN 'L' THEN 2
WHEN 'XL' THEN 3
WHEN 'XXL' THEN 4
ELSE 10
END, size, id"
)
You might want to move it to scope so in case you need to add another size_name there is only one place to change
With active record enums:
enum size_name: { s: 0, l: 1, xl: 2, xxl: 3 }
That way, you can still assign the field by the string/symbol, but the underlying data will actually be an integer, so you can just use order(:size_name, :size) to sort by size_name and size.
Also this way you can add index to speed up ordering

How do I get a value by index from a nested table in lua?

I've been making a game with the LOVE2D game engine, and I've stumbled across an issue. I want to access a variable inside a nested table, but I don't know how.
Here's my code right now:
local roomNum = 1
local rooms = { r1 = { complete = false, name = "Room 1" }
if rooms[roomNum].complete == true then --problematic line
--do stuff
end
If I replace rooms[roomNum].complete with rooms.r1.complete then it works.
Any help would be appreciated!
'http://lua-users.org/wiki/TablesTutorial'
The provided link gives easy to understand examples on tables in Lua, so it may prove a useful resource in the future.
As for the why the replacement code worked, a dictionary is just sets of key/value pairs (kvp) . In examples from other languages, these pairs are normally shown as something like KeyValuePair.
In your case, you are using a variation on how dictionaries are used. As you have seen, you can use numbered indexes like room[1], or you can use a string like room["kitchen"]. It gets interesting when you provide a set of data to initialize the dictionary.
Building off of the provided data, you have the following:
local rooms = { r1 = { complete = false, name = "Room 1" }
r1 is equivalent to using rooms["r1"] without the dataset. In providing the dataset, any "named" Key can be referenced like it is a property of the dictionary (think of classes with public getter/setter). For the named keys of a dataset, you can provide a key as numbers as well.
local rooms = { [1] = { complete = false, name = "Room 1" }
This indexing fits the direction you were headed on providing a room index. So, you could either swap the dataset to use integers instead of r1, r2 and so on, or you could concatenate r and the index numbering. That is pretty much up to you. Keep in mind as you go further down nesting the same rules apply. So, complete could look like rooms[1].complete, rooms["r1" ].complete, or rooms.r1.complete.

F# -> Seq to Map

I'm trying to load all my Categories from the database and then map them to a Map (dictionary?), however when I use the following code:
[<StructuralComparison>]
type Category = {
mutable Id: string;
Name: string;
SavePath: string;
Tags: ResizeArray<Tag> }
let categories = session.Query<Category>()
|> Seq.map(fun z -> (z,0))
|> Map.ofSeq
it simply throws an error that says:
The struct, record or union type
'Category' has the
'StructuralComparison' attribute but
the component type 'ResizeArray'
does not satisfy the 'comparison'
constraint
I have absolutely no clue about what to do, so any help is appreciated!
F# is rightly complaining that ResizeArray<_> doesn't support structural comparison. ResizeArray<_> instances are mutable and don't support structural comparison, and you therefore can't use them as fields of records which are used as keys to Map<_,_>s (which are sorted by key). You have a few options:
Have Tags use a collection type that does support structural comparison (such as an immutable Tag list).
Use [<CustomComparison>] instead of [<StructuralComparison>], which requires implementing IComparable.
Use a mutable dictionary (or another relevant collection type) instead of a Map. Try using the dict function instead of Map.ofSeq, for instance.
The problem here is that by adding StructuralComparison attribute to the type Category you've asked F# to use structural comparison when comparing instances of Category. In short it will compare every member individually to see if they are equal to determine if two instances of Category are equal.
This puts an implicit constraint on every member of Category to themselves be comparable. The type ResizeArray<Tag> is generating an error because it's not comparable. This is true for most collection types.
In order to get rid of this error you'll need to make the ResizeArray<T> type comparable or choose a different key for the Map. Don has a great blog post that goes into this topic in depth and provides a number of different ways to achieve this. It's very much worth the read
http://blogs.msdn.com/b/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx

Resources