chan11347

chan11347

so i look up the zip(list_of_lists) in github and it have some example

Zips corresponding elements from each list in list_of_lists.
The zipping finishes as soon as any list terminates.

Examples

      iex> List.zip([[1, 2], [3, 4], [5, 6]])
      [{1, 3, 5}, {2, 4, 6}]
      iex> List.zip([[1, 2], [3], [5, 6]])
      [{1, 3, 5}]

i want to make the def function like above

def zip([]), do: []

def zip(list_of_lists) when is_list(list_of_lists) do
    do_zip(list_of_lists, [])
end

i want to understand what is list of lists and how to represent it when every list is not the same, thanks

Showing Posts 1 to 10

lucaong

lucaong

If I understand, you want to reimplement List.zip\1, is that correct? That’s a nice exercise.

The list_of_lists argument is, as the name says, a list of several lists, possibly of different lengths. The zip function iterates through all the lists, grouping the nth element from each list into a tuple. It stops as soon as the shortest list is exhausted.

What exactly you want to understand better? Is something in particular confusing you?

chan11347

chan11347 OP

i am trying to put the code into the exs and run it with erlang

	def cross([]) do
	0
	end

	def cross(list_of_lists) when is_list(list_of_lists) do
    cross(list_of_lists, [])
	end

and the return is said is a undefined function, so i want know is that anything just wrong since i cannot compilation with these code

lucaong

lucaong

Well, there are a number of things that are wrong. First of all, the function must be defined within a module. Second, the recursive call to cross uses the wrong number of arguments (cross is defined with one argument, but is called with two arguments in cross(list_of_lists, [])).

Also, this recursive call would never complete, because the list_of_list is passed unchanged, and therefore will never get to the base case of empty list (unless it’s empty to start with).

Usually, when implementing recursion, you start with a base case, and you make sure that the recursive call moves in the direction of the base case (if the base case is an empty list, the list should be consumed at each recursive call, so that it will eventually be empty).

For example, let’s define a function that takes a list of numbers and returns the sum:

defmodule Sum do
  # Version of sum with one single argument, calling the two
  # arguments version with the initial `partial_sum` of 0
  def sum(list) do
    sum(list, 0)
  end

  # Base case, the given list is empty, so we can just return the
  # sum accumulated so far
  def sum([], partial_sum) do
    partial_sum
  end

  # If the list is not empty, we sum the first element and call
  # the function recursively with the rest of the list, so it shrinks
  # at each call, eventually becoming empty
  def sum([first | rest], partial_sum) do
    sum(rest, partial_sum + first)
  end
end

Now, you can call the defined function:

Sum.sum([1, 2, 3, 4, 5])
#=> 15
chan11347

chan11347 OP

defmodule Ans0 do
	def cross([],[]) do
	0
	end
	
	def cross([h1|t1],[h2|t2]) do
	{h1,h2}
	cross([t1],[t2])
	end

end

so it should be like this?

NobbZ

NobbZ

No.

The {h1, h2} line does not have any effect, its an unused value.

The cross([t1], [t2]) line will eventually just loop forever as cross([[]], [[]]). You do not need to wrap the tails in a list, as they already are lists.

Also your base case will just return 0, which would make your function return 0 regardless of the input, if there wasn’t the infinite loop in the other case. As you want to construct a list in the function, you need to return a list. What do you think how should the return look like?

In the other case, you need to construct the return value from the tuple you already build and forget, and the result of the recursive call. Something like [the_tuple | result_of_the_recursive_call].

lucaong

lucaong

Well, you are making progresses, but there are still things that won’t really work in this code.

First of all, the first definition of cross, for empty lists, returns 0. I don’t know what you are trying to do (are you implementing zip?), but that seems at odd with the rest of the program. What is your expected output? If you are using recursion, your base clause should return that.

Second, the tuple {h1, h2} is created but never used nor returned, so right now it is useless. If you are implementing zip, you’ll want to accumulate these tuples to finally return them in a list.

Remember that Elixir functions always return the result of their last expression.

Also, t1 and t2 are already lists. If you wrap them in brackets you will get nested lists, which is probably not what you want.

Here’s a nudge in the right direction:

defmodule Ans0 do
  # In the public 2 argument version you can call a private
  # 3 arguments version with an added argument to accumulate
  # step by step the final result
  def cross(a, b) do
    cross(a, b, [])
  end

  defp cross([], [], accumulated) do
    # I leave this to you, reason on what must be returned
    # when you reach the base case
  end

  defp cross([head1 | tail1], [head2 | tail2], accumulated) do
    # Here we prepend {head1, head2} to the accumulated
    # result, and pass it with the tails of the lists to the next
    # iteration
    cross(tail1, tail2, [{head1, head2} | accumulated])
  end
end

When implementing it, pay attention to the order of the accumulated list, and also beware that this implementation would only work if the list arguments have the same length. You can add base cases to account for different lengths (I leave this to you).

In general, my recommendation is that you take your time to learn the basics of Elixir before you jump into recursion exercises: it will make it easier to understand why something is not working as it should.

chan11347

chan11347 OP

this is what i try to do about it

chan11347

chan11347 OP

update:

defmodule Ans0 do

	def cross([],[]) do
	end

	def cross([h1|t1],[h2|t2]) do
	[{h1,h2}|cross(t1,t2)]
	end

end
lud

lud

This returns nil, so your final result will be [{'a', 1},{'b', 2}, {'c', 3} | nil] which is called an improper list because it contains a non-list element as the final element (well it is more complicated but I can’t explain it properly).
Note that
[{'a', 1}, {'b', 2}, {'c', 3} | nil]
and
[{'a', 1}, {'b', 2}, {'c', 3}, nil]

are different.

The first one is equivalent to
[{'a', 1} | [{'b', 2} | [{'c', 3} | nil]]]
The second one to
[{'a', 1} | [{'b', 2} | [{'c', 3} | [nil | []]]]]

lucaong

lucaong

You are very close. As @lud explained, you still have an issue with the base case.

In order to solve it for good, think about your base case: if you would call Ans0.cross([], []), what would you expect as a result? Right now, you get nil, but is this what you really should expect? Remember that in Elixir nil is different from [].

— All posts loaded —

Where Next? Top

Trending in Questions Top

water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
bradley
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
unaware8150
Hello folks! So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
Alvinkariuki
How Can I Optimise Compile Time Dependencies I have been building an elixir application for about 2 years now. Many modules and files ha...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New

Other Trending Topics Top

budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews