I'm looking at GADT definitions, and they use objects instead of records. I was wondering why, as it seems like objects are pretty much never used in general in OCaml. Is there a difference?
For example:
type (_, _, _) Basic.t +=
| Field : ('field1, 'field2, < field1 : 'field1 ; field2 : 'field2 ; .. >) t
Objects offer a unique type system feature, called row polymorphism. It is hard to tell without any more context why is row polymorphism required in this particular example, I can only tell that this constructor represents a family of row polymorphic types of objects that has at least two methods, field1 and field2 of type 'field1 and 'field2 correspondingly.
Related
I have a ListVector and value [[1,2,3,4,5]] in VectorSchemaRoot and I could see its value in IDEA.
I use following code to write the VectorSchemaRoot variable and get the byte array
val out = new ByteArrayOutputStream()
val writer = new ArrowStreamWriter(vectorSchemaRoot, null, out)
writer.start()
writer.writeBatch()
writer.end()
out.close()
val byteArr = out.toByteArray
And read back
val allocator = new RootAllocator(Int.MaxValue)
val reader = new ArrowStreamReader(new ByteArrayInputStream(byteArr), allocator)
while (reader.loadNextBatch()) {
val schemaRoot = reader.getVectorSchemaRoot
schemaRoot
}
The schema is correct, but the list is empty []
However, I use other types of values, like char, bit, the result read from the byteArr is correct(non-empty).
How to fix the ListVector empty issue?
Finally I used just basic classes.
The StructVector, ListVector are complex classes, and according to my test, they do not bring speed or memory benefit over just using basic classes. And the documents for complex classes are very few.
Thus basic classes is recommended. And just use List of Fields to make the schema of them, could also get the structured vector.
Suppose I define type
type person = { last_name: string; first_name: string; age: int};;
let person1 = {last_name="Doe"; first_name="John"; age=30};;
How can I print
Last name : Doe
First name : John
Age : 30
I thought using
match person1 with
| {last_name=ln; first_name=fn; age=a} -> print_string ...;;
but it seems not the way to go. If person1 and person were defined to be a dictionary with 1000 elements, then that solution doesn't hold.
Is there a better way to challenge that problem? Be aware that I have to use the functional paradigm. So I can't use while or for loop directly
It's hard to answer your question because you seem to have two different ideas of your type simultaneously. You can't have a type that's both a record and a dictionary. It's not possible.
Generally speaking, a dictionary is a collection of things. The convention for collections in OCaml is that they have a function named iter that traverses the collection.
Imagine you have an abstract collection defined by a module C. Conventionally you'll have a type 'a C.t for each collection, where 'a is the type of the elements of the collection. You'll also have (conventionally) a function C.iter of this type:
C.iter : ('a -> unit) -> 'a C.t -> unit
This means you can pass a function (like your printing function) to C.iter, and then also pass a collection. The iter function will traverse the collection and call your function for every element.
In your case the module C would define the dictionary you're imagining, and the type person C.t would be the type of a dictionary of the records you show above. The function C.iter would have the type (person -> unit) -> person C.t -> unit. In other words, it would take a function and apply it to all the persons in the dictionary, one after the other.
We can't really say more unless we know the details of the dictionary that you are planning to create.
So in an exercise I am given a list like ["xyz", True, 42]. The question was if that is a valid expression in Haskell and what the type of that expression is.
A list can only hold homogenous types but the type of "xyz"is [Char], the type of True is Bool and the type of 42 is Num p => p. That is different types so I can't put them into a list.
That's what I thought. But the given answer to that exercise is "Yes, it is a valid expression. Show-instance!."
Why is it a valid expression although the types of the list elements are different and what is meant with show-instance? I'm thinking of something like superclasses from object oriented languages but I thought this is not how Haskell works.
If we are allowed to define some more context, we can make this a valid expression, for instance with:
import Data.String(IsString(fromString))
instance IsString Bool where
fromString [] = False
fromString _ = True
instance Num Bool where
(+) = (||)
(*) = (&&)
abs = id
signum = id
fromInteger 0 = False
fromInteger _ = True
negate = not
(here I used the truthiness of Python to convert from an Integer and String literal)
Then we can write it with the OverloadedStrings pragma:
{-# LANGUAGE OverloadedStrings #-}
the_list = ["xyz", True, 42]
This will then be equivalent to:
Prelude Data.String> ["xyz", True, 42]
[True,True,True]
But note that the list still contains only Bools, we only made Bool an instance of IsString and Num to enable us to convert string literals and number literals to Bools.
A list of heterogeneous types is not possible in Haskell, and since by default a Bool is not a Num, we thus can not parse that expression without adding some extra magic.
An additional note is that it is valid Haskell grammar: syntactically there is nothing wrong, it is only in the next stage of the compiler: type checking, etc. that it will raise errors, since the syntax is nonsensical.
My lecturer gave me a hint to check for Existential types in Haskell.
I produced a working example from the description from the link above:
{-# LANGUAGE ExistentialQuantification #-}
module Main where
data Showable = forall a . Show a => MkShowable a
pack:: Show a => a -> Showable
pack a= MkShowable a
instance Show Showable where
show (MkShowable a) = show a
hlist :: [Showable]
hlist = [pack "xyz", pack True, pack 42]
main :: IO ()
main = do
putStrLn "Heterogenous list 'camouflaged' as Showable:"
print hlist
This works and produces indeed the input from the exercise. The datatype extension for Existential Quantification in the first line is necessary.
My explanation (I might have gotten something wrong though):
I create a new type Showablewith one constructor MkShowable that takes any value a as long as it is in typeclass Show and thus makes a Showable out of it.
The method pack makes a Show a become a Showable by using the constructor MkShowable I described in 1.
Showable is made an instance of Show-typeclass and tells that if a Showable(MkShowable a) is to be shown, simply show a. So we can easily print our Showables.
Furthermore I created a (heterogenous) list hlist of type [Showable]and packed the values from my example into it, using pack. The list is printed in the main function.
This really reminds me of object-oriented programming.
I've been digging into Lua's source code, both the C source from their website and the lua files from Lua on Windows. I found something odd that I can't find any information about, as to why they chose to do this.
There are some methods in the string library that allows OOP calling, by attaching the method to the string like this:
string.format(s, e1, e2, ...)
s:format(e1, e2, ...)
So I dug into the source code for the module table, and found that functions like table.remove(), also allows for the same thing.
Here's the source code from UnorderedArray.lua:
function add(self, value)
self[#self + 1] = value
end
function remove(self, index)
local size = #self
if index == size then
self[size] = nil
elseif (index > 0) and (index < size) then
self[index], self[size] = self[size], nil
end
end
Which indicate that the functions should support the colon method. Lo' and behold when I copy table into my new list, the methods carry over. Here's an example using table.insert as a method:
function copy(obj, seen) -- Recursive function to copy a table with tables
if type(obj) ~= 'table' then return obj end
if seen and seen[obj] then return seen[obj] end
local s = seen or {}
local res = setmetatable({}, getmetatable(obj))
s[obj] = res
for k, v in pairs(obj) do res[copy(k, s)] = copy(v, s) end
return res
end
function count(list) -- Count a list because #table doesn't work on keyindexed tables
local sum = 0; for i,v in pairs(list) do sum = sum + 1 end; print("Length: " .. sum)
end
function pts(s) print(tostring(s)) end -- Macro function
local list = {1, 2, 3}
pts(list.insert) --> nil
pts(table["insert"]) --> function: 0xA682A8
pts(list["insert"]) --> nil
list = copy(_G.table)
pts(table["insert"]) --> function: 0xA682A8
pts(list["insert"]) --> function: 0xA682A8
count(list) --> Length: 9
list:insert(-1, "test")
count(list) --> Length: 10
Was Lua 5.1 and newer supposed to support table methods like the string library but they decided to not implement the meta method?
EDIT:
I'll explain it a little further so people understand.
Strings have metamethods attached that you can use on the strings OOP style.
s = "test"
s:sub(1,1)
But tables doesn't. Even though the methods in the table's source code allow for it using "self" functions. So the following code doesn't work:
t = {1,2,3}
t:remove(#t)
The function has a self member defined in the argument (UnorderedArray.lua:25: function remove(self,index)).
You can find the metamethods of strings by using:
for i,v in pairs(getmetatable('').__index) do
print(i, tostring(v))
end
which prints the list of all methods available for strings:
sub function: 0xB4ABC8
upper function: 0xB4AB08
len function: 0xB4A110
gfind function: 0xB4A410
rep function: 0xB4AD88
find function: 0xB4A370
match function: 0xB4AE08
char function: 0xB4A430
dump function: 0xB4A310
gmatch function: 0xB4A410
reverse function: 0xB4AE48
byte function: 0xB4A170
format function: 0xB4A0F0
gsub function: 0xB4A130
lower function: 0xB4AC28
If you attach the module/library table to a table like Oka showed in the example, you can use the methods that table has just the same way the string metamethods work.
The question is: Why would Lua developers allow metamethods of strings by default but tables doesn't even though table's library and it's methods allow it in the source code?
The question was answered: It would allow a developer of a module or program to alter the metatables of all tables in the program, leading to the result where a table would behave differently from vanilla Lua when used in a program. It's different if you implement a class of a data type (say: vectors) and change the metamethods of that specific class and table, instead of changing all of Lua's standard table metamethods. This also slightly overlaps with operator overloading.
If I'm understanding your question correctly, you're asking why it is not possible to do the following:
local tab = {}
tab:insert('value')
Having tables spawn with a default metatable and __index breaks some assumptions that one would have about tables.
Mainly, empty tables should be empty. If tables were to spawn with an __index metamethod lookup for the insert, sort, etc., methods, it would break the assumption that an empty table should not respond to any members.
This becomes an issue if you're using a table as a cache or memo, and you need to check if the 'insert', or 'sort' strings exist or not (think arbitrary user input). You'd need to use rawget to solve a problem that didn't need to be there in the first place.
Empty tables should also be orphans. Meaning that they should have no relations without the programmer explicitly giving them relations. Tables are the only complex data structure available in Lua, and are the foundation for a lot of programs. They need to be free and flexible. Pairing them with the the table table as a default metatable creates some inconsistencies. For example, not all tables can make use of the generic sort function - a weird cruft for dictionary-like tables.
Additionally, consider that you're utilizing a library, and that library's author has told you that a certain function returns a densely packed table (i.e., an array), so you figure that you can call :sort(...) on the returned table. What if the library author has changed the metatable of that return table? Now your code no longer works, and any generic functions built on top of a _:sort(...) paradigm can't accept these tables.
Basically put, strings and tables are two very different beasts. Strings are immutable, static, and their contents are predictable. Tables are mutable, transient, and very unpredictable.
It's much, much easier to add this in when you need it, instead of baking it into the language. A very simple function:
local meta = { __index = table }
_G.T = function (tab)
if tab ~= nil then
local tab_t = type(tab)
if tab_t ~= 'table' then
error(("`table' expected, got: `%s'"):format(tab_t), 0)
end
end
return setmetatable(tab or {}, meta)
end
Now any time you want a table that responds to functions found in the table table, just prefix it with a T.
local foo = T {}
foo:insert('bar')
print(#foo) --> 1
How do I write a simple ABAP Unit Assert statement to check if any call, expression or other statement evaluates to true?
I can't see any basic assert() or assert_true() methods in CL_AUNIT_ASSERT while I'd expect those to be very common. I can approximate such an assert as follows, but is there no cleaner way?
cl_aunit_assert=>assert_equals(
act = boolc( lv_value > 100 OR lv_value < 2 )
exp = abap_true ).
cl_aunit_assert=>assert_equals(
act = mo_model->is_active )
exp = abap_true ).
Depending on your SAP NetWeaver stack you can (or should) use the updated ABAP Unit Class CL_ABAP_UNIT_ASSERT. This class is available at a Basis-Release >= 7.02. SAP declared this class as 'FINAL' so it´s impossible to inherit from it, but on the other side they added some ASSERT-Methods like the ASSERT_TRUE Method!
Here is a possible usage of this method:
cl_abap_unit_assert=>assert_true(
exporting
act = m_ref_foo->is_bar( l_some_var )
msg = 'is_bar Method fails with Input { l_some_var }'
).
For the releases I have access to, there's probably no shorter way than the one you outlined. You can create a subclass of CL_AUNIT_ASSERT and add your own static ASSERT_TRUE method. It's not a bad idea to do so and at the same time make your local ABAP Unit test class a subclass of that ZCL_AUNIT_ASSERT - this way, you can omit the cl_aunit_assert=> prefix which will save some keystrokes.
You cannot see such methods because there is no boolean type in ABAP.
While in Java, C++ or C, you are able to assign a result of a condition to a variable, like this
int i = 5;
boolean result = i > 3;
You cannot do the same thing in ABAP as there is no boolean type. Therefore what in other languages is a one liner, in ABAP it will always be more prolix.
DATA: i TYPE i VALUE 5.
DATA: result TYPE abap_bool.
IF i > 3.
result = abap_true.
ELSE.
result = abap_false.
ENDIF.
The thing you used seems to be a new feature, that has been recently added to the language and most of the customers will not be using for a long time. Also the CL_AUNIT_ASSERT class was created way before the new elements came to the language.
So right now, there is a possibility to write the above thing as one liner. However there is still no boolean type in the language.
DATA: i TYPE i VALUE 5.
DATA: result TYPE abap_bool.
result = boolc( i > 3 ).
On the other hand, there is no boolean type, but you could simply use ASSERT_INITIAL or ASSERT_NOT_INITIAL in this case, as boolean is emulated by either X (true) or space (false). The latter is an initial value in ABAP.
The cleanest way is to just fail:
if value > limit.
cl_abap_unit_assert=>fail( ).
endif.
Or a more informative:
cl_abap_unit=>fail( msg = 'Limit exceeded' ).