Пустой `vec()` не является ложным

Рассмотрим этот пример:

#!/usr/bin/env perl

my $vec0;

# set the first bit of vec0 to false
vec($vec0, 0, 1) = 0;

print "vec0 is " . length($vec0) . " bytes long\n";

if ($vec0) {
  # what
  print "vec0 is True!\n";
}

vec, используемый в оценке, кажется (почти) всегда истинным - это потому, что vec на самом деле является строкой, и поэтому $vec0 - это строка, содержащая "\0", которая не является ложной в соответствии с Perl: только строки "" и "0" " являются ложными.

(кроме того: это False, несмотря на то, что оно не равно нулю:

vec($vec0, 5, 1) = 1;
vec($vec0, 4, 1) = 1;

потому что 0x30 — это ASCII-код 0)

Хорошо: каков «правильный» способ проверки «пустого» вектора (т.е. всех битов, установленных в 0)? Подсчитать биты с помощью unpack, проверить регулярное выражение m/^\0*$/, «нормализовать» все векторы, отсекая пустые байты с конца? Кажется, это должна быть решенная проблема... и почему Perl не обрабатывает vec волшебным образом для true/false?

Можете ли вы указать, что именно вы считаете «пустым»?

zdim 25.05.2024 01:12
if ( vec($vec0, 0, 1) )?
TLP 25.05.2024 01:21

@zdim — Все биты в векторе не установлены (0)

Greg Kennedy 25.05.2024 01:27

Знаете ли вы общее количество битов, которые вы будете использовать? например если вы знаете, что всего будет 8 бит, вы можете установить отдельные биты следующим образом: vec($vec0, 4, 1) = 1 # set bit 4 затем, чтобы проверить, установлен ли какой-либо из 8 бит, вы проверяете if (vec($vec0, 0, 8))

joe90_supermarionation 25.05.2024 01:37

«Все биты в векторе не установлены (0)» — возможно, я не понимаю какую-то часть того, что вам нужно, но если вы преобразуете это в (битовую) строку с помощью my $bits = unpack("b*", $vector);, то в числовом контексте это будет равен нулю ($bits == 0), если все биты не установлены. Я не могу придумать более прямой способ, с самим вектором.

zdim 25.05.2024 04:36

(Или с помощью $bits это легко проверить по кусочкам или по маске из такого количества нулевых битов)

zdim 25.05.2024 04:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
93
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Ниже приведен, вероятно, самый быстрый подход без внешнего кода C:

$vec0 !~ tr/\x01-\xFF//   # True if "empty".
$vec0 =~ tr/\x01-\xFF//   # True if not "empty".

Если вы используете векторы фиксированной ширины, вы можете создать еще один вектор соответствующей длины, состоящий из всех нулей, и сравнить его с теми, которые вы хотите протестировать.

my $zero_vec = pack "C*", (0) x $length_in_bytes;

# ...

if ($vec0 ne $zero_vec) {
  print "vec0 is True!\n";
}

Я также нашел старый модуль на CPAN, String::BitCount, который подсчитывает количество установленных битов в строке:

use String::BitCount;

# ...

if (BitCount($vec0)) {
  print "vec0 is True!\n";
}

или, может быть, регулярное выражение:

if ($vec0 !~ m/\A\x00+\z/) {
  print "vec0 is True!\n";
}
pack "C*", (0) x $length_in_bytes упрощается до "\0" x $length_in_bytes
ikegami 25.05.2024 02:52

Чтобы проверить это

Все биты в векторе не установлены (0).

может преобразовать его в (битовую) строку с помощью my $bits = unpack("b*", $vector), а затем в числовом контексте, который будет равен нулю ($bits == 0), если все биты не установлены. Так

if ( unpack("b*", $vec0) == 0 ) { say "All bits zero" }

Это сокращение для проверки того, что биты не установлены, ( unpack("b*", $vec0) | 0 ) == 0.

Я не думаю, что у vec есть какой-то «волшебный» способ это проверить.

Другие вопросы по теме