Functions · 15
More about functions
Scope, returning several values, and passing functions as values.
Three ways to get more out of functions: knowing where a variable lives (scope), returning two values, and passing a function like a value.
The example below gets the smallest and largest of some numbers in one call, passes a test function to count the even numbers and the numbers that are 10 or more, and records in a variable outside the functions how many tests were made in total.
checks = 0 # 함수 밖 변수: 프로그램이 끝날 때까지 남아요 def is_even(x): return x % 2 == 0 def is_big(x): return x >= 10 def min_max(nums): lo = hi = nums[0] for x in nums: lo = min(lo, x) hi = max(hi, x) return lo, hi # 두 값을 함께 돌려줘요 def count_if(nums, test): # test에는 함수가 들어와요 global checks # 밖의 변수를 바꾸겠다고 알려요 count = 0 # 함수 안 변수: 부를 때마다 새로 만들어져요 for x in nums: checks += 1 if test(x): count += 1 return count nums = list(map(int, input().split()))lo, hi = min_max(nums)print(lo, hi)print(count_if(nums, is_even))print(count_if(nums, is_big))print(checks)let checks = 0; // 함수 밖 변수: 프로그램이 끝날 때까지 남아요 function isEven(x) { return x % 2 === 0;} function isBig(x) { return x >= 10;} function minMax(nums) { let lo = nums[0], hi = nums[0]; for (const x of nums) { lo = Math.min(lo, x); hi = Math.max(hi, x); } return [lo, hi]; // 두 값을 배열에 담아 돌려줘요} function countIf(nums, test) { // test에는 함수가 들어와요 let count = 0; // 함수 안 변수: 부를 때마다 새로 만들어져요 for (const x of nums) { checks++; // 밖의 변수를 바꿔요 if (test(x)) count++; } return count;} const nums = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const [lo, hi] = minMax(nums);console.log(lo + " " + hi);console.log(countIf(nums, isEven));console.log(countIf(nums, isBig));console.log(checks);import { readFileSync } from "node:fs"; let checks = 0; // 함수 밖 변수: 프로그램이 끝날 때까지 남아요 function isEven(x: number): boolean { return x % 2 === 0;} function isBig(x: number): boolean { return x >= 10;} function minMax(nums: number[]): [number, number] { let lo = nums[0], hi = nums[0]; for (const x of nums) { lo = Math.min(lo, x); hi = Math.max(hi, x); } return [lo, hi]; // 두 값을 배열(튜플)에 담아 돌려줘요} function countIf(nums: number[], test: (x: number) => boolean): number { // test에는 함수가 들어와요 let count = 0; // 함수 안 변수: 부를 때마다 새로 만들어져요 for (const x of nums) { checks++; // 밖의 변수를 바꿔요 if (test(x)) count++; } return count;} const nums: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const [lo, hi] = minMax(nums);console.log(lo + " " + hi);console.log(countIf(nums, isEven));console.log(countIf(nums, isBig));console.log(checks);import java.util.*;import java.util.function.IntPredicate; public class Main { static int checks = 0; // 함수 밖 변수(클래스의 static 필드): 프로그램이 끝날 때까지 남아요 static boolean isEven(int x) { return x % 2 == 0; } static boolean isBig(int x) { return x >= 10; } static int[] minMax(List<Integer> nums) { int lo = nums.get(0), hi = nums.get(0); for (int x : nums) { lo = Math.min(lo, x); hi = Math.max(hi, x); } return new int[] {lo, hi}; // 두 값을 배열에 담아 돌려줘요 } static int countIf(List<Integer> nums, IntPredicate test) { // test에는 함수가 들어와요 int count = 0; // 함수 안 변수: 부를 때마다 새로 만들어져요 for (int x : nums) { checks++; // 밖의 변수를 바꿔요 if (test.test(x)) count++; } return count; } public static void main(String[] args) { Scanner in = new Scanner(System.in); List<Integer> nums = new ArrayList<>(); while (in.hasNextInt()) nums.add(in.nextInt()); int[] r = minMax(nums); int lo = r[0], hi = r[1]; System.out.println(lo + " " + hi); System.out.println(countIf(nums, Main::isEven)); System.out.println(countIf(nums, Main::isBig)); System.out.println(checks); }}using System;using System.Linq; class Program{ static int checks = 0; // 함수 밖 변수(클래스의 static 필드): 프로그램이 끝날 때까지 남아요 static bool IsEven(int x) { return x % 2 == 0; } static bool IsBig(int x) { return x >= 10; } static (int, int) MinMax(int[] nums) { int lo = nums[0], hi = nums[0]; foreach (int x in nums) { lo = Math.Min(lo, x); hi = Math.Max(hi, x); } return (lo, hi); // 두 값을 튜플로 함께 돌려줘요 } static int CountIf(int[] nums, Func<int, bool> test) // test에는 함수가 들어와요 { int count = 0; // 함수 안 변수: 부를 때마다 새로 만들어져요 foreach (int x in nums) { checks++; // 밖의 변수를 바꿔요 if (test(x)) count++; } return count; } static void Main() { int[] nums = Console.ReadLine().Split().Select(int.Parse).ToArray(); var (lo, hi) = MinMax(nums); Console.WriteLine(lo + " " + hi); Console.WriteLine(CountIf(nums, IsEven)); Console.WriteLine(CountIf(nums, IsBig)); Console.WriteLine(checks); }}#include <algorithm>#include <functional>#include <iostream>#include <utility>#include <vector> int checks = 0; // 함수 밖 변수(전역 변수): 프로그램이 끝날 때까지 남아요 bool isEven(int x) { return x % 2 == 0;} bool isBig(int x) { return x >= 10;} std::pair<int, int> minMax(const std::vector<int>& nums) { int lo = nums[0], hi = nums[0]; for (int x : nums) { lo = std::min(lo, x); hi = std::max(hi, x); } return {lo, hi}; // 두 값을 pair에 담아 돌려줘요} int countIf(const std::vector<int>& nums, const std::function<bool(int)>& test) { // test에는 함수가 들어와요 int count = 0; // 함수 안 변수: 부를 때마다 새로 만들어져요 for (int x : nums) { checks++; // 밖의 변수를 바꿔요 if (test(x)) count++; } return count;} int main() { std::vector<int> nums; int v; while (std::cin >> v) nums.push_back(v); auto [lo, hi] = minMax(nums); std::cout << lo << ' ' << hi << '\n'; std::cout << countIf(nums, isEven) << '\n'; std::cout << countIf(nums, isBig) << '\n'; std::cout << checks << '\n';}#include <stdio.h> int checks = 0; // 함수 밖 변수(전역 변수): 프로그램이 끝날 때까지 남아요 int is_even(int x) { return x % 2 == 0;} int is_big(int x) { return x >= 10;} // 돌려줄 값이 둘이라, 결과를 적어 줄 자리(주소)를 받아요void min_max(const int *nums, int n, int *lo, int *hi) { *lo = *hi = nums[0]; for (int i = 0; i < n; i++) { if (nums[i] < *lo) *lo = nums[i]; if (nums[i] > *hi) *hi = nums[i]; }} int count_if(const int *nums, int n, int (*test)(int)) { // test에는 함수(의 주소)가 들어와요 int count = 0; // 함수 안 변수: 부를 때마다 새로 만들어져요 for (int i = 0; i < n; i++) { checks++; // 밖의 변수를 바꿔요 if (test(nums[i])) count++; } return count;} int main(void) { int nums[100], n = 0; while (n < 100 && scanf("%d", &nums[n]) == 1) n++; int lo, hi; min_max(nums, n, &lo, &hi); printf("%d %d\n", lo, hi); printf("%d\n", count_if(nums, n, is_even)); printf("%d\n", count_if(nums, n, is_big)); printf("%d\n", checks); return 0;}checks = 0; // 함수 밖(맨 위) 변수: 함수 안에서도 같은 변수예요 isEven(x){ return x % 2 == 0;} isBig(x){ return x >= 10;} minMax(nums){ lo = nums[0]; hi = nums[0]; foreach (x in nums) { lo = Mathf.Min(lo, x); hi = Mathf.Max(hi, x); } return [lo, hi]; // 두 값을 목록에 담아 돌려줘요} countIf(nums, test){ count = 0; // 함수 안 변수: 부를 때마다 새로 만들어져요 foreach (x in nums) { checks++; // 밖의 변수를 바꿔요 if (test(x)) { count++; } } return count;} nums = Console.ReadNumbers();r = minMax(nums);Console.WriteLine(r[0] + " " + r[1]);Console.WriteLine(countIf(nums, isEven));Console.WriteLine(countIf(nums, isBig));Console.WriteLine(checks);4 15 8 23 6 7
4 23 3 2 12
Key points
- Every variable has a place where it lives (its scope).
A variable created inside a function is usable only inside that function and is made fresh on every call.
The example'scountstarts again from 0 each time. - A variable created outside the functions stays until the program ends.
The example'scheckskeeps its value across the two calls and ends up as 12. - How a function changes an outside variable differs by language.
When outside variables are changed from many places it gets hard to find where a value changed.
So use one only for a single program-wide tally like the example'schecks, take what a function needs as parameters, and hand back a result such ascountwithreturn. - To return two values, pack them into one bundle and unpack it on the receiving side.
The bundle (tuple, array, pair, list) differs by language.
C takes the addresses to write the results into. - A function is a value too, so you can pass it to another function.
The example uses one counting function for both "count the even numbers" and "count the numbers that are 10 or more".
Only the part that differs (the test) is pulled out into a function and passed in. - When passing, write just the name, with no parentheses.
is_evenis the function itself;is_even(4)is the result of calling it.
How each language writes it
| Python | To only read an outside variable inside a function, just use it; to change it, write global checks at the top of the function.Return two values with return lo, hi (a tuple) and receive them with lo, hi = min_max(nums).Pass a function by name, as in count_if(nums, is_even); make a short test on the spot with lambda x: x >= 10 |
|---|---|
| JavaScript | A variable created with let outside the functions can be read and changed inside them with no marker.Declaring the same name again with let inside a function makes a different variable from the outside one.Return two values with return [lo, hi]; and receive them with const [lo, hi] = minMax(nums);.Pass a function as in countIf(nums, isEven); a short test is an arrow function (x) => x >= 10 |
| TypeScript | Same as JavaScript. The type for returning two values is [number, number], and a parameter that takes a function is written like test: (x: number) => boolean |
| Java | A variable cannot sit outside a class, so an outside variable is a static field of the class (static int checks = 0;).Return two values in an int[], or define record MinMax(int lo, int hi) {} and return that.Take a function as IntPredicate test and call it with test.test(x); pass Main::isEven or a lambda x -> x >= 10.Changing a local variable of main inside a lambda is a compile error |
| C# | A variable cannot sit outside a class, so an outside variable is a static field of the class.Return two values as a tuple (int, int) with return (lo, hi); and receive them with var (lo, hi) = MinMax(nums);.out parameters (out int lo) are another way.Take a function as Func<int, bool> test; pass IsEven or a lambda x => x >= 10 |
| C++ | A variable written outside the functions is a global variable, which any function can read and change. Return two values as a std::pair<int, int> with return {lo, hi}; and receive them with auto [lo, hi] = minMax(nums);.Take a function as std::function<bool(int)> (<functional>); pass isEven or a lambda [](int x) { return x >= 10; } |
| C | A variable written outside the functions is a global variable. There is no syntax for returning two values, so take the addresses to write the results into, as the example does ( int *lo, int *hi, called with &lo, &hi), or return a struct.Take a function as a function pointer int (*test)(int) and pass its name, as in count_if(nums, n, is_even).There are no lambdas |
| Craykon | A variable created at the top level is the same variable inside functions, so they read and change it with no marker. A variable first created inside a function is usable only in that function. Return two values in a list, return [lo, hi];, and take them out with r[0] and r[1].There are no lambdas, so pass a named function, as in countIf(nums, isEven) |
Common mistakes
Trying to return two values with return lo, hi;JavaScript · C · C++
function minMax(nums) {
let lo = nums[0], hi = nums[0];
for (const x of nums) { lo = Math.min(lo, x); hi = Math.max(hi, x); }
return lo, hi;
}
console.log(minMax([4, 15, 8]));→ 15 — the comma operator keeps only the last value, so just hi comes back. C and C++ compile it with only a warning and give 15 as well. TypeScript stops it in the type check (TS2695)
In JavaScript write return [lo, hi];; in C++ return a std::pair with return {lo, hi};; in C take addresses or return a struct.return lo, hi returning two values is Python.
Changing an outside variable without globalPython
checks = 0
def check(x):
checks += 1
return x % 2 == 0
print(check(4))→ UnboundLocalError: cannot access local variable 'checks' where it is not associated with a value — a name that is assigned inside a function is treated as that function's own variable, so it stops when trying to add 1 to a checks that has no value yet
Write global checks at the top of the function.
It is not needed when you only read the variable.
A variable inside a function with the same name as a top-level oneCraykon
total = 100;
twice(x)
{
total = x * 2;
return total;
}
Console.WriteLine(twice(4));
Console.WriteLine(total);→ 8, 8 — the function did not create a new variable; it changed the top-level total, and the 100 is gone
Give a variable used only inside a function a different name from the top-level variables.
A parameter is the function's own variable even when the name is the same.
In the other languages, creating it inside the function with let total or int total (in Python, assigning without global) makes a separate variable, and the output is 8, 100.
If you add parentheses when passing a function, as in
countIf(nums, isEven()), you are not passing it but calling it right there.JavaScript stops with
TypeError: test is not a function and Python with TypeError: is_even() missing 1 required positional argument: 'x'.TypeScript reports it in the type check, and Craykon reports an error saying isEven needs 1 value but got 0.