Iterate through array and return itself - crystal-lang

This code: p [1, 2].each{ "foo" } produces nil, whilst I want it to put [1, 2] after iteration. How-to in Crystal?

Use tap:
p [1, 2].tap &.each { "foo" } # => [1, 2]
It yields self to the block and then returns self.
Another option (not preferable) could be creating a custom method that simply returns self after doing each:
class Array
def each_with_self
each { |x| yield x }
self
end
end
p [1, 2].each_with_self { "foo" } # => [1, 2]

For the case you are asking it could be enough to use parens in p(..) since p returns the argument as result.
p([1, 2]).each{ "foo" }
This behavior of p serves for doing easy inspections in the middle of an expression, i.e. changing foo(bar, baz) to foo(p(bar), baz).
As for #each, in crystal it was decided to return nil to improve the generated code since the value is not used most of the time. This also prevents the generation of some unions at the end of the day.

Related

How to verify no null elements in list, Kotlin

I'd like to check a List<Int?> for nulls and if no nulls exist, then allow the List to proceed as a List<Int>, otherwise use an emptyList()
This is what I came up with:
var noNullElements: List<Int> = emptyList()
if (listWithPossibleNullElements.all { it != null }) {
noNullElements = listWithPossibleNullElements as List<Int>
}
//do something with noNullElements list
I'd be shocked if this was the best, most idiomatic way.
Solution
There are many acceptable solutions below, but the one I chose was a combination of the solutions
fun getSafeList(list: List<Int?>): List<Int> =if (null in list) emptyList() else list.requireNoNulls()
Here's a one liner extension function:
inline fun <reified T : Any> Iterable<T?>.filterNoneNull(): Iterable<T>? =
takeIf { null !in it }?.requireNoNulls()
takeIf {} - a scope function that will return null if the lambda evaluates to false
null !in it - use the in operator function to determine if the list contains null
finally, if takeIf {} returns a non-null value, filterNotNull() will convert the element type from the nullable T? to non-null T
Note that it will return null if the provided Iterable<T?> contains null, else List<T>, in case it's important to differentiate between the provided list being empty, or containing null. An alternative can be provided using the elvis operator.
Example usage - run in Kotlin Playground:
fun main() {
val listA: List<Int?> = listOf(1, 2, 3, null)
// since listA contains 'null', the result is 'null'
println(listA.filterNoneNull())
// prints: null
// provide an alternative, using the elvis operator
println(listA.filterNoneNull() ?: emptyList<Int>())
// prints: []
val listB: List<Int> = listOf(1, 2, 3)
// since listB does not contain null, the same list is returned
println(listB.filterNoneNull())
// prints: [1, 2, 3]
}
inline fun <reified T : Any> Iterable<T?>.filterNoneNull(): Iterable<T>? =
takeIf { null !in it }?.requireNoNulls()
Note: I edited the question and replaced filterNotNull() with requireNoNulls(), as the latter will not instantiate a new list
Check with contains for the existence of at least one null value:
val noNullElements = if (list.contains(null)) emptyList() else list.map { it!! }
Edit: Added this extension function:
fun List<Int?>.castToIntOrEmpty() =
if (this.contains(null)) emptyList() else this.map { it as Int }
val noNullElements = list.castToIntOrEmpty()
Example with no null elements:
val list: List<Int?> = List(10) { it }
// list is: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
val noNullElements = if (list.contains(null)) emptyList() else list.map { it!! }
println(noNullElements) // Output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Example with some (or all) null elements:
val list: List<Int?> = List(10) { if (it % 2 == 0) it else null }
// list is: [0, null, 2, null, 4, null, 6, null, 8, null]
val nullElements = if (list.contains(null)) emptyList() else list.map { it!! }
println(nullElements) // Output: []
I think your problem is you want to take a generic List<Int?> type and treat it as a List<Int>, which means casting it. Because List<Int?> isn't a subtype of List<Int> (although the inverse is true, as Joffrey points out in the comments) you basically have to perform an unchecked cast in this situation:
if (list.contains(null)) emptyList else list as List<Int>
The compiler isn't smart enough to determine that this is a safe cast at runtime (and you have to be able to make that guarantee yourself, e.g. ensuring the list isn't being modified elsewhere to include a null after the check passes) so you'll get an unchecked cast warning. The documentation on generics goes into your options, but if you really want to pass in a List<Int?> and treat it as a List<Int>, you'll have to suppress that warning:
An unchecked cast warning can be suppressed by annotating the statement or the declaration where it occurs with #Suppress("UNCHECKED_CAST")
I'd argue the more idiomatic approach is to just create a new List<Int> instead of trying to cast the original one to a different generic type, or to make the original list provider pass a List<Int>? instead (i.e. null if there were any non-null elements) which is maybe just moving the problem - but it really depends on what you're doing.
You can easily create filtered copies and compare it to the original to decide whether to use it, or write a for loop building a new list that short-circuits if you hit a null, all those kinds of things. If you want to check first and only copy if you need it, lukas.j's answer has more examples (including a couple that throw exceptions, like requireNoNulls()) so you have a lot of options, and there are different tradeoffs - it really depends on what you're doing and where the bottlenecks are (if any). Things can get a bit awkward when you work with generics, so some situations don't end up looking as neat as you'd like!
Try using filterNotNull:
val noNullElements: List<Int> = listWithPossibleNullElements.filterNotNull()

groovy: adding and removing elements from a defined variable within a class

I'm trying to get this class to run but I keep running into issues. I'm new to Java and not sure if I am doing this correctly. If someone could just help me out with the addition of elements to a list I can figure out the rest!
class ListPractice implements Testable {
def mylist = [4,5,6]
/**
* Adds a set of elements to the mylist variable
*
* #param elts The elements to be added
*/
def addToList(List elts) {
def newlist = getMylist()+List
return newlist
}
#Override
void testMe() {
addToList([7,8,9])
assert getMylist() == [4,5,6,7,8,9]
assert getMylist() == [7,8,9]
}
}
You are adding List instead of elts. The method you are looking for is addAll:
groovy:000> l = [1,2,3]
===> [1, 2, 3]
groovy:000> l.addAll([4,5,6])
===> true
groovy:000> l
===> [1, 2, 3, 4, 5, 6]
Since addtoList sounds already as if you plan to mutate this, why create a
new one, return it, and later never use it? So: mylist.addAll(elts) should
be enough.
related:
just write mylist instead of getMylist() - it's groovy
your comment on addToList says set but accepys a list. Sets have
different characteristics than lists, so it's confusing. If you rename it
to addToMylist you might not even need a comment at all.

Get the first element of a list idiomatically in Groovy

Let the code speak first
def bars = foo.listBars()
def firstBar = bars ? bars.first() : null
def firstBarBetter = foo.listBars()?.getAt(0)
Is there a more elegant or idiomatic way to get the first element of a list, or null if it's not possible? (I wouldn't consider a try-catch block elegant here.)
Not sure using find is most elegant or idiomatic, but it is concise and wont throw an IndexOutOfBoundsException.
def foo
foo = ['bar', 'baz']
assert "bar" == foo?.find { true }
foo = []
assert null == foo?.find { true }
foo = null
assert null == foo?.find { true }
--Update Groovy 1.8.1
you can simply use foo?.find() without the closure. It will return the first Groovy Truth element in the list or null if foo is null or the list is empty.
You could also do
foo[0]
This will throw a NullPointerException when foo is null, but it will return a null value on an empty list, unlike foo.first() which will throw an exception on empty.
Since Groovy 1.8.1 we can use the methods take() and drop(). With the take() method we get items from the beginning of the List. We pass the number of items we want as an argument to the method.
To remove items from the beginning of the List we can use the drop() method. Pass the number of items to drop as an argument to the method.
Note that the original list is not changed, the result of take()/drop() method is a new list.
def a = [1,2,3,4]
println(a.drop(2))
println(a.take(2))
println(a.take(0))
println(a)
*******************
Output:
[3, 4]
[1, 2]
[]
[1, 2, 3, 4]

Scala insert into list at specific locations

This is the problem that I did solve, however being a total imperative Scala noob, I feel I found something totally not elegant. Any ideas of improvement appreciated.
val l1 = 4 :: 1 :: 2 :: 3 :: 4 :: Nil // original list
val insert = List(88,99) // list I want to insert on certain places
// method that finds all indexes of a particular element in a particular list
def indexesOf(element:Any, inList:List[Any]) = {
var indexes = List[Int]()
for(i <- 0 until inList.length) {
if(inList(i) == element) indexes = indexes :+ i
}
indexes
}
var indexes = indexesOf(4, l1) // get indexes where 4 appears in the original list
println(indexes)
var result = List[Any]()
// iterate through indexes and insert in front
for(i <- 0 until indexes.length) {
var prev = if(i == 0) 0 else indexes(i-1)
result = result ::: l1.slice(prev, indexes(i)) ::: insert
}
result = result ::: l1.drop(indexes.last) // append the last bit from original list
println(result)
I was thinking more elegant solution would be achievable with something like this, but that's just pure speculation.
var final:List[Any] = (0 /: indexes) {(final, i) => final ::: ins ::: l1.slice(i, indexes(i))
def insert[A](xs: List[A], extra: List[A])(p: A => Boolean) = {
xs.map(x => if (p(x)) extra ::: List(x) else List(x)).flatten
}
scala> insert(List(4,1,2,3,4),List(88,99)){_ == 4}
res3: List[Int] = List(88, 99, 4, 1, 2, 3, 88, 99, 4)
Edit: explanation added.
Our goal here is to insert a list (called extra) in front of selected elements in another list (here called xs--commonly used for lists, as if one thing is x then lots of them must be the plural xs). We want this to work on any type of list we might have, so we annotate it with the generic type [A].
Which elements are candidates for insertion? When writing the function, we don't know, so we provide a function that says true or false for each element (p: A => Boolean).
Now, for each element in the list x, we check--should we make the insertion (i.e. is p(x) true)? If yes, we just build it: extra ::: List(x) is just the elements of extra followed by the single item x. (It might be better to write this as extra :+ x--add the single item at the end.) If no, we have only the single item, but we make it List(x) instead of just x because we want everything to have the same type. So now, if we have something like
4 1 2 3 4
and our condition is that we insert 5 6 before 4, we generate
List(5 6 4) List(1) List(2) List(3) List(5 6 4)
This is exactly what we want, except we have a list of lists. To get rid of the inner lists and flatten everything into a single list, we just call flatten.
The flatten trick is cute, I wouldn't have thought of using map here myself. From my perspective this problem is a typical application for a fold, as you want go through the list and "collect" something (the result list). As we don't want our result list backwards, foldRight (a.k.a. :\) is here the right version:
def insert[A](xs: List[A], extra: List[A])(p: A => Boolean) =
xs.foldRight(List[A]())((x,xs) => if (p(x)) extra ::: (x :: xs) else x :: xs)
Here's another possibility, using Seq#patch to handle the actual inserts. You need to foldRight so that later indices are handled first (inserts modify the indices of all elements after the insert, so it would be tricky otherwise).
def insert[A](xs: Seq[A], ys: Seq[A])(pred: A => Boolean) = {
val positions = xs.zipWithIndex filter(x => pred(x._1)) map(_._2)
positions.foldRight(xs) { (pos, xs) => xs patch (pos, ys, 0) }
}

scala return on first Some in list

I have a list l:List[T1] and currently im doing the following:
myfun : T1 -> Option[T2]
val x: Option[T2] = l.map{ myfun(l) }.flatten.find(_=>true)
The myfun function returns None or Some, flatten throws away all the None's and find returns the first element of the list if any.
This seems a bit hacky to me. Im thinking that there might exist some for-comprehension or similar that will do this a bit less wasteful or more clever.
For example: I dont need any subsequent answers if myfun returns any Some during the map of the list l.
How about:
l.toStream flatMap (myfun andThen (_.toList)) headOption
Stream is lazy, so it won't map everything in advance, but it won't remap things either. Instead of flattening things, convert Option to List so that flatMap can be used.
In addition to using toStream to make the search lazy, we can use Stream::collectFirst:
List(1, 2, 3, 4, 5, 6, 7, 8).toStream.map(myfun).collectFirst { case Some(d) => d }
// Option[String] = Some(hello)
// given def function(i: Int): Option[String] = if (i == 5) Some("hello") else None
This:
Transforms the List into a Stream in order to stop the search early.
Transforms elements using myFun as Option[T]s.
Collects the first mapped element which is not None and extract it.
Starting Scala 2.13, with the deprecation of Streams in favor of LazyLists, this would become:
List(1, 2, 3, 4, 5, 6, 7, 8).to(LazyList).map(function).collectFirst { case Some(d) => d }
Well, this is almost, but not quite
val x = (l flatMap myfun).headOption
But you are returning a Option rather than a List from myfun, so this may not work. If so (I've no REPL to hand) then try instead:
val x = (l flatMap(myfun(_).toList)).headOption
Well, the for-comprehension equivalent is pretty easy
(for(x<-l, y<-myfun(x)) yield y).headOption
which, if you actually do the the translation works out the same as what oxbow_lakes gave. Assuming reasonable laziness of List.flatmap, this is both a clean and efficient solution.
As of 2017, the previous answers seem to be outdated. I ran some benchmarks (list of 10 million Ints, first match roughly in the middle, Scala 2.12.3, Java 1.8.0, 1.8 GHz Intel Core i5). Unless otherwise noted, list and map have the following types:
list: scala.collection.immutable.List
map: A => Option[B]
Simply call map on the list: ~1000 ms
list.map(map).find(_.isDefined).flatten
First call toStream on the list: ~1200 ms
list.toStream.map(map).find(_.isDefined).flatten
Call toStream.flatMap on the list: ~450 ms
list.toStream.flatMap(map(_).toList).headOption
Call flatMap on the list: ~100 ms
list.flatMap(map(_).toList).headOption
First call iterator on the list: ~35 ms
list.iterator.map(map).find(_.isDefined).flatten
Recursive function find(): ~25 ms
def find[A,B](list: scala.collection.immutable.List[A], map: A => Option[B]) : Option[B] = {
list match {
case Nil => None
case head::tail => map(head) match {
case None => find(tail, map)
case result # Some(_) => result
}
}
}
Iterative function find(): ~25 ms
def find[A,B](list: scala.collection.immutable.List[A], map: A => Option[B]) : Option[B] = {
for (elem <- list) {
val result = map(elem)
if (result.isDefined) return result
}
return None
}
You can further speed up things by using Java instead of Scala collections and a less functional style.
Loop over indices in java.util.ArrayList: ~15 ms
def find[A,B](list: java.util.ArrayList[A], map: A => Option[B]) : Option[B] = {
var i = 0
while (i < list.size()) {
val result = map(list.get(i))
if (result.isDefined) return result
i += 1
}
return None
}
Loop over indices in java.util.ArrayList with function returning null instead of None: ~10 ms
def find[A,B](list: java.util.ArrayList[A], map: A => B) : Option[B] = {
var i = 0
while (i < list.size()) {
val result = map(list.get(i))
if (result != null) return Some(result)
i += 1
}
return None
}
(Of course, one would usually declare the parameter type as java.util.List, not java.util.ArrayList. I chose the latter here because it's the class I used for the benchmarks. Other implementations of java.util.List will show different performance - most will be worse.)