#Is it impossible to get a List() element by index?

1 messages · Page 1 of 1 (latest)

ivory cipher
#

I didn't find some way to get an item from a List(String) using an index. Like list[1]

fn main() {
    let list = [1, 2];
    let first_index = list[0];

    println!("{:?}", first_index);
}

This code in Rust produces 1 as output. How can I do something similar on Gleam? And just out of curiosity, why is list[1] not a valid code in Gleam?

wraith zealot
#

You (ideally) shouldn't

#

In rust you're using an array, in Gleam we used linked lists

#

the performance characteristics of list[x] in Rust is O(1)

#

in gleam that same thing would be O(n)

#

The usual advice is use a different data structure ™️

ivory cipher
#

gotcha, thank you!

spice scaffold
#

if you need something at or near the head of a list then pattern matching works well for that, but yeah if you're arbitrarily reaching deep into a list then you'll want to look for something more appropriate

untold zealot
#

why is list[1] not a valid code in Gleam?
It actually is! But it's misleading to format code like that.

pub fn main(list) {
  list[1]
}

If you run the formatter you'll see what it actually is

pub fn main(list) {
  list
  [1]
}
#

Indexing is very rare in functional programming, so rare that I don't think we even have a package with a vector/array type yet.

#

Any time you reach for indexing you may want to stop and think if there's a functional solution you could use instead, using pattern matching etc.

ivory cipher
#

Indexing is very rare in functional programming
I'm learning function programming with Gleam, tbh. And I thought something similar when I faced there was no obvious way to do what I want - so I'm probably doing something wrong

oblique mauve
#

Some examples: if you're thinking of using indexes in a loop, you can use recursion + pattern matching, while if you're using it in a fixed length list (let's say storing first + last name), you should be probably using tuples

untold zealot
#

Don't worry! It takes some time to learn all the little patterns when adopting a new programming paradigm

#

We can help with any specific places you get stuck too

spice scaffold
#

or using a custom type with fields you can access

ivory cipher
oblique mauve
#

But if it's random, why do you need an index?

ivory cipher
untold zealot
#

Could you give an example of what your code might look like?

oblique mauve
#

I'd just generate the data itself tbf, but (as Louis pointed out), I may be misinterpreting

junior sinew
ivory cipher
# untold zealot Could you give an example of what your code might look like?
pub fn get_random_index(list: List(String)) -> Int {
  let len = list.length(list)
  int.random(len)
}

pub fn first_name(sex: String) -> String {
  case sex {
    "male" -> {
      let index = get_random_index(first_name.generic)
        // something
      name
    }

    _ -> {
      "Todo later"
    }
  }
}

The goal is to take some random string value from a List(String).
The List(String) is the first_name.generic - but I probably need to move it to some other data structure. first_name.generic is a list with some names

#

Is tuples the answer?

ivory cipher
untold zealot
ivory cipher
untold zealot
#

No I mean how are you making it

ivory cipher
#

Oh
pub const generic: List(String) = ["names"]

untold zealot
#

Yeah you don't want a list

ivory cipher
#

But now I think that I should move it to tuples

untold zealot
#

You can't do random index into tuples

#

Use a case expression

valid gull
#

Can't you do list.shuffle and list.first?

ivory cipher
valid gull
#

Ah it's gonna be a big one

untold zealot
#

Unless you're happy carrying some state around the only fast option is a case expression

ivory cipher
untold zealot
#

Yes, it compiles to a jump table

#

Which is what your array index would compile to

ivory cipher
#

interesting

untold zealot
#

Alternatively you could design your API to be stateful