-
Notifications
You must be signed in to change notification settings - Fork 682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[css-values] Add round()/floor()/ceil() functions #2513
Comments
I think Alternatively, with |
Though I see the more full featured request which spawned this issue was closed for lack of use cases (#905), I am at least encountering sub-pixel issues all the time when trying to create responsive component styles. And they are becoming more and more of an issue if I want to actually utilize recent "wins" on the css unit front. Not being able to coerce a rounded pixel value from things like this.. --offset: calc(50vw * 0.2 / var(--count)); ...often forces me to compute dimensions with javscript, adding hacky resize listeners and thrashing my layout, to then use position: sticky;
left: calc(var(--offset) * 2);
width: calc(100vw - (var(--offset) * 2));
scroll-snap-align: end; Because the used sub-pixel values here can render the authors intended layout mostly futile. Pretty sure that solving rounding would save a lot of headaches
I find the sub-pixel case as the most pertinent for a rounding solution, though the suggestion from @Crissov for all lengths sounds worthwhile. Especially when I think of |
@jonjohnjohnson Thank you for the more concrete example. @Loirooriol The more CSSy alternative to |
I think floor(), ceil(), and round() all have very reasonable use-cases. (And adding any one of them allows one to implement the other two, so might as well add them as a group.) Unlike in JS, CSS doesn't have a default scale to round to, so all three of the functions will require a precision. The only difference between floor/ceil/round will be which direction is favored when the value is between steps of the precision. As you say, @Crissov, an alternative syntax would be add a single round() function, and let it have an optional third argument that dictates how to round it, like |
Should/could CSS have a default scale for this purpose? Or can these functions locally define a default for an omitted precision parameter? |
FWIW, css-rhythm already introduces a set of keywords for rounding behavior: @astearns Setting the default scale for |
I think such a function should accept At first glance it can seem that a To avoid confusion, for dimensions I think it's better to require the precision like |
Ah, allowing a default precision for plain numbers, but requiring an explicit one for dimensions, works for me. And yes, I definitely think that authors would expect @Crissov Ooh, good catch on remembering about the Rhythm keywords. |
Since some authors are accustomed to Javascript/EcmaScript functions and the CSS WG strives for compatibility where possible and reasonable, here is a list of related standard methods of the
|
When Tab asked for opinions on Twitter, my first instinct was to favour separate round/ceil/floor rather than the more verbose function+keyword modifier option. And ceil and floor are familiar from JS. But for people who don't have an imperative programming or mathematical background, maybe they are just more confusing jargon? If the preference is to have a single function that does all three operations, I'd recommend (a) putting the keyword in front, and (b) using the keywords from CSS Rhythm, so it's more readable as an English phrase: "round up", "round down", "round nearest" (which would still be the default for round):
(The Another thought: it might be useful to have a third value for specifying an offset/initial value from which to start the step function. For example: round(var(--count), 2); /* rounds to the nearest even number */
round(var(--count), 2, 1); /* rounds to the nearest odd number */
/* or imagine setting the width of a grid container to neatly fit the child items… */
round(down, 100%, /* take 100% width and round it down */
var(--item-width) + var(--gap-width), /* to a multiple of the total width for an item + gap */
-1 * var(--gap-width) ); /* except that the first item doesn't need a gap, so subtract it */ |
I also thought about this, but not sure if it's worth it since it can be trivially achieved with
Also, if there is an offset, I guess towards-zero and away-from-zero would actually be towards-offset and away-from-offset? |
Putting the keyword first does read better, yeah. And as Oriol said, I don't think an offset is necessary here; it complicates the grammar with a third unlabeled calculation, which isn't great design, and it's pretty easy to handle yourself in the rare cases it's needed. ("Rare" based on my own usage of rounding across my CS career; I've only needed to do that a handful of times.) In this case I think there's good reason to avoid pure JS compat. As stated before, there's no way to do rounding with unitted values without specifying a precision, which already breaks compat somewhat. (I don't think it's reasonable to only allow rounding on numbers; we're currently only applying that restriction on the two functions where it's necessary to do so due to the power changing; everything else is adapted to unitted values appropriately.) Also, ceil is just a terrible, terrible name. It's difficult for me to remember whether it's ei or ie, and I know I'm not alone. Using the Rhythm keywords reads much better, I think. fround() doesn't seem necessary; I'm not even really sure what it's purpose is in JS, let alone what one could possible want it for in CSS. Similarly, trunc() is just "round towards zero"; if we include it we should use the same naming scheme as the others. |
For posterity, the results of my Twitter poll are roughly 3:1 in favor of separate functions instead of a single function with keywords. As usual, polls are far from binding; people's spot opinions don't always reflect their long-term opinions, and there are many constraints in play besides initial preference as well. |
I'm not sure I buy the argument that the standard names are confusing in this case. If the names are new and confusing, I'd assume so is having to think about the different rounding modes at all. If that's the case, writing In the case of floor and ceiling specifically, I'd also imagine that those either are or will be introduced to more people at an earlier age as math education includes more discrete math as more computer science education is introduced. So, at least for those two, I think there would be a long term benefit for calling them by their more standardized names. |
I didn't say the names were confusing, I said they're hard to spell. (Tho Amelia does suggest they may be confusing.) I have to type ciel/ceil every time and see which one works. I'll note, tho, that I don't actually know offhand what |
Well, thatʼs just anecdotal, not empirical, evidence to support a certain decision. English is not my native language and I find the spelling of ceiling not hard at all. PS: Nevertheless, I'm not really in favor of introducing |
The CSS Working Group just discussed
The full IRC log of that discussion<bkardell_> topic: VAlues and units round()/floor()/ceil()/mod() (tab)<bkardell_> TabAtkins: As we knew would probably happen, as we started suggesting math functions, people wanted more math functions <bkardell_> TabAtkins: problems in the past the prevented these, we have solved those - so this issue is specifically about adding round and mod functions - they are all similar under the hood <astearns> github: https://github.com//issues/2513 <bkardell_> TabAtkins: the big question for me is whether we want to add these as 4 function names or 1 with a mode? <bkardell_> chrisl: which will people be most familliar with <bkardell_> TabAtkins: another concern is spelling, for me ceil or ciel is confusing to me - I suspect I am not the only one... my suggestion is we go with round function <bkardell_> TabAtkins: Any ideas, comments suggestions? <fantasai> TabAtkins writes on the blackboard: round(keyword? calc, calc, ...) <fantasai> s/, ...// <bkardell_> TabAtkins: round(keyword?, calc, calc) -- the second being precision you want <bkardell_> leaverou: is there any precedent of having a single function like this in any language? <bkardell_> TabAtkins: we have several functions with optional keywords in css <bkardell_> leaverou: fair enough <chris> rrsagent, here <RRSAgent> See https://www.w3.org/2020/01/22-css-irc#T09-34-34 <bkardell_> fremy: when does round function happen <bkardell_> TabAtkins: same time as all of the math functions <bkardell_> jensimmons: it seems like we asked this on twitter and we are now seeming to go against their express intent in this, admittedly non-scientific poll <chris> alias sky ceiling <bkardell_> fantasai: people who come from a math/programming background get 'floor' and 'ceiling' but as someone coming new to programming you won't know that <bkardell_> myles: it's a math term <bkardell_> fantasai: i didn't learn it, I don't think a lot of us did. For discoverability of people who are not already familliar with these terms it is a better model <chris> round-up | round-down | round-truncate <Rossen__> q? <bkardell_> leaverou: don't forget that there is limited value in asking people because they will always trend toward whatever they already know <bkardell_> rachelandrew: people will trend toward the simplest things <bkardell_> dbaron: is this proposal written in the issue? I didn't find it in these comments? <bkardell_> fremy: one of them was from amelia, I thin <bkardell_> s/thin/think <fantasai> s/better model/better model, because all four functions that do almost the same thing with slight variations are under the same feature. With the 4 separate functions, you have to now that they exist, and it's harder to find them unless you already know their names/ <bkardell_> jensimmons: consistency in css is a strong argument <fantasai> i/jensimmons/rossen?: Could bake the keywords into the function name, like round-up(), round-down(), etc./ <bkardell_> Rossen__: it sounds like we all are agreeing that one function with an optional keyword... <jensimmons> (uh, that’s not what I said.) I said — it makes sense to me what fantasai said, that it is basically one function / one feature — with several different ways to do it. <bkardell_> florian: I was just looking and ruby has this pattern actually, the one we're suggesting <dbaron> you can get to 8 functions with up|down|towards-zero|away-from-zero|nearest-half-goes-up|nearest-half-goes-down|nearest-half-goes-away-from-zero|nearest-half-goes-towards-zero <florian> https://ruby-doc.org/core-2.5.3/Float.html#method-i-round <bkardell_> Rossen__: prior art, agreement in the room, any objections <fantasai> i/jensimmons/fantasai: There's no typing benefit to doing that, should just follow the CSS pattern we have in gradients, cross-fade(), etc. to put the keyword in the parens/ <dbaron> and I think the comment pointed to was https://github.com//issues/2513#issuecomment-565736728 <bkardell_> Rossen__: ok resolved <bkardell_> RESOLVED: Adopt a round function with keywords detailing which behavior <bkardell_> TabAtkins: mod() same deal - it's similar to mod() anywhere else, but I suggest we don't match javascript here <bkardell_> myles: there is value in matching js here <dbaron> Tab is suggesting that the sign of the result should match the sign of the second argument, not the first <bkardell_> TabAtkins: from what I can tell, most of the time people want the sign of the modulus, not the sign of the first arg <bkardell_> myles: I don't have a strong opinion, I think there is a strong case to match JavaScript though <Rossen__> q? <bkardell_> TabAtkins: I feel mathematical mod is more sensible, how you probably learned in school - not as done in js as adopted from Java as adopted from C <bkardell_> jensimmons: I think matching JavaScript is valuable <astearns> +1 to jensimmons <bkardell_> Rossen__: breaking the relationship to JavaScript seem to be a bad default - people use JavaScript to create CSS <fantasai> fantasai: what are the use cases for modding negative numbers? <bkardell_> dbaron: if I am imagining some step pattern or some kind of thing you would create here - it does seem like what TabAtkins is saying is going to be more natural <fantasai> +1 <bkardell_> TabAtkins: there seems to be good argument both ways <bkardell_> fantasai: I would lean toward dbaron argument <fantasai> fantasai: people who use JS are going to be more comfortable mucking about with mod functions to get the behavior they want <dbaron> I was arguing that if you're using mod() to generate step patterns or something like that, if we use the JS mod(), you'll have to be careful to avoid inputting negative numbers (or, as Tab said, using multiple-mod() workarounds for that). <fantasai> s/both ways/both ways; and you can use mod + add + mod calc pattern to switch behaviors if needed/ <bkardell_> bkardell_: Lots of preprocessors have functions like this -- which do they have, does it matter? <bkardell_> TabAtkins: they don't seem to have an example <bkardell_> TabAtkins: they don't seem to have an example in sass <fantasai> fantasai: but this way the people who are just trying to get their CSS to work don't have to try so hard <bkardell_> TabAtkins: just looking at the wikipedia page, you can see this problem demonstrated <bkardell_> TabAtkins: it's very easy to just accidentally go negative and then you will have broken code, whereas the way I am suggesting here you have to be more intentional about it <bkardell_> TabAtkins: good argument in general that matching js is good - but we have also agreed that it is maybe less intuitive <bkardell_> TabAtkins: what do we want to do? <bkardell_> Rossen__: straw poll for the initial thing, we can always change our minds <bkardell_> Rossen__: 1) align with js 2) align with 'math' <leaverou2> 2 <fremy> 2 <TabAtkins> 2 <heycam> 1 <bkardell_> 1 <jfkthame> 1 <iank_> 1 <Rossen__> 1 <stantonm> 1 <rachelandrew> 1 <emilio> 1 <florian> 2 <astearns> 1 <cbiesinger> 2 <jensimmons> on behalf of dbaron — 2 <bkardell_> myles: 1 <bkardell_> tess: 1 <bkardell_> bkardell_: 1 <bkardell_> TabAtkins: 11 to 10, I think we have to leave this as an open issue <bkardell_> Rossen__: any objections to adding the mod() function with an open issue about....what it actually does? <fantasai> i/TabAtkins/[various people have lost connectivity] <fantasai> s/connectivity/connectivity; Tab runs an offline poll/ <jensimmons> the vote in the room was 12 for Option 1 (align with JS) and 11 for Option 2 (align with math) <bkardell_> RESOLVED: add the mod function with an open issue about behavior <fantasai> It was 11 against 11 of the people in the room; myles claimed to vote for Tess, but she wasn't here for the oral arguments :p |
The CSS Working Group just discussed The full IRC log of that discussion<dbaron> Topic: update on mod() function<TabAtkins> https://twitter.com/tabatkins/status/1219936010961915905 <emilio> ScribeNick: emilio <astearns> github: https://github.com//issues/2513 <emilio> TabAtkins: so the poll I started yesterday about mod has ended <emilio> ... had some fair results, and the contradictory results I expected <emilio> ... so 3/2 in favor of JS, 9/1 in favor of math, depending on how you ask <emilio> ... so the conclusion is that most people just write buggy code and they think / want math semantics <fantasai> /JS/JS semantics if you ask directly/ <emilio> ... there's also a lot of discussion in the replies about use-cases <jensimmons> link to poll?? <fantasai> s/favor of math/favor of math if you ask them about a basic computation/ <emilio> ... and it seems math is a better suit to fix those use cases <emilio> jfkthame: would people be better off with explicit is-odd / even functions <fantasai> https://twitter.com/tabatkins/status/1219936010961915905 <fantasai> https://twitter.com/tabatkins/status/1219936010961915905 <emilio> TabAtkins: they sometimes use it as a proxy for odd / even, but it's not general of course <TabAtkins> https://twitter.com/tabatkins/status/1219939184682717184 <emilio> TabAtkins: so no decision for now yet unless the room is convinced, but worth thinking about it and we can peek this up at a later call <emilio> TabAtkins: how does the room feel? Did anyone change their mind? <emilio> myles_: I guess there's a third option which is not defining what negatives does <emilio> TabAtkins: that's what C++ does and that's evil <emilio> myles_: I didn't mean to return unicorns but just explicitly return 0 or something <emilio> TabAtkins: it seems negatives could be common, I wouldn't want that <emilio> Rossen: seems not many opinions have changed so let's move on |
Added round() in 90ff717. mod() is waiting on final resolution on naming; I hope to resolve that today. |
The CSS Working Group just discussed
The full IRC log of that discussion<fremy> Topic: mod() mode<astearns> github: https://github.com//issues/2513 <TabAtkins> https://en.wikipedia.org/wiki/Modulo_operation#In_programming_languages <fremy> TabAtkins: I was thinking about this, and looking at the wikipedia article... <fremy> TabAtkins: there is a lot of divergence <fremy> TabAtkins: but there is one constant <fremy> TabAtkins: if a language has a pair, mod works like Math and % works like JS <fantasai> s/%/rem/ <fremy> TabAtkins: in particular, <<<<>>>> language does this, because they came to the same conclusion <heycam> q+ <fremy> TabAtkins: so my proposal, is to add the two functions <fantasai> s/<<<>>>>/Web Assembly/ <fremy> leaverou: why are we adding functions and not an operator <fremy> TabAtkins: more complex <leaverou> s/why are we adding functions and not an operator/why are these functions and not operators?/ <fremy> TabAtkins: and also it's not an operator in all languages anyway <fantasai> I support Tab's proposal fwiw <fremy> myles: why dont' we want mod to be like js? <florian> +1 <florian> s/+1/+1 to tab's proposal/ <fremy> TabAtkins: javascript doesn't have a function, just an operator that works like rem <fremy> myles: but then we make CSS more powerful than JS, while JS was intended to be math-complete while CSS is not <fremy> hober: I think the point of this exercise was to reduce differences in differences between the platform languages <fremy> hober: I'm confused why we want to introduce inconsistencies <RossenF2F> q? <fremy> hober: It might be reasonable to ask somebody from TC39 to consider adding the other function, and mimick their response <fremy> TabAtkins: I don't believe it's correct to say that we want to minimize the difference between the two languages <fremy> TabAtkins: our goal is to give designers the functions they need to get the layouts they want <fremy> TabAtkins: which is why we didn't add the hyperbolic functions because there are no known use case <fremy> TabAtkins: and to reply to the "more powerful question", we already do that <fremy> TabAtkins: for instance, we have a more complex round function, and that is useful because rouding is important to us <fremy> TabAtkins: so I don't want to say we should not innovate beyond JS <fremy> TabAtkins: but we should only do it if there's an use case <astearns> ack heycam <astearns> Zakim, close queue <Zakim> ok, astearns, the speaker queue is closed <fremy> heycam: If we really wanted to match JS, we would do an operator, not a mod function in the first place <fremy> heycam: but I was on the queue to say something else <fremy> heycam: it's confusing to have an unit called rem, and a function called rem <fremy> heycam: I would like to avoid it <fremy> myles: an author might think it gives you the size of a rem <fremy> TabAtkins: it would not work, and authors would realize that <astearns> ack fantasai <Zakim> fantasai, you wanted to point out that JS doesn't have a mod function, it has a % operator, so either way we have to pick a name, picking rem() as that name is perfectly fine <fremy> fantasai: also, I want to point out that log doesn't do console.log <fremy> fantasai: also, I agree, % is not a function in JS, not a function <myles> q? <fremy> fantasai: so, if we add a mod() function we don't have to match JS, we can do something useful <fremy> myles: log is a very different example, because we just cannot console.log in JS <fremy> myles: but here we are doing the same thing <fremy> TabAtkins: we have functions that can absorb css timing resolutions from houdini <fremy> TabAtkins: the paint api when it gets called gives you timing information <fremy> astearns: I don't think this is gonna get narrowed down today <fremy> TabAtkins: but, we want to check if we can ship this <fremy> TabAtkins: so can we strawpoll or record objections? <fremy> <debate on the options between people> <fremy> RossenF2F: the new option is that we have both mod and rem <fremy> florian: I think we should just have a decision yes or no on the adoption of this approval <fremy> astearns: yeah, let's do this <fremy> hober: I am worried about the form of this strawpol <fremy> hober: because we are not agreeing on an alternative <fremy> astearns: yes, but if we say no, we don't do anything and defer for another day <TabAtkins> 1. Resolve to add mod() (math behavior) and rem() (JS behavior) <TabAtkins> 2. Continue thinking about the desired mod-ish behavior in the issue, resolve sometime later. <fantasai> 1 <florian> 1 <TabAtkins> 1 <faceless> 1 <leaverou> 1 <hober> 2 <dbaron> 1 <RossenF2F> 1 <fremy> 1 <tantek> 1 because YOLO <stantonm> 1 <rachelandrew> 1 <astearns> abstain <jfkthame> 1 <heycam> 1 <fremy> 15/22 said 1 <RossenF2F> mod(15/22) <fremy> astearns: proposed resolution is thus to add both mod() and rem() <fremy> astearns: does anybody object? <TabAtkins> It's 13 for option 1, 1 for option 2 <fremy> RESOLVED: the mod() and rem() functions are to be added to CSS, one with math behavor, the other with JS behavior <TabAtkins> ScribeNick: TabAtkins <leaverou> Chris can't vote due to lack of connectivity, but he votes 1 |
So, to clarify:
|
Exactly correct, yes. Another way to think of it is, repeatedly add or subtract the absolute value of the step-size to bring the value closer to zero. rem() stops when the value is as close as possible to zero without crossing it; mod() stops when the number is between 0 and the step. There's a bunch of equivalent formulations. |
(Oh yeah, not exactly correct: mod() is not always positive, it's always the sign of the second argument. rem() is always the sign of the first argument.) |
I agree with this concern, but I can't think of a better proposal other than writing out |
Why? Why not default to using the unit that is next to the number, so that Being able to use single parameters in the most common use cases is an important ease of use consideration. You don’t then need to recall if they are space separated or comma separated, for one thing, or which parameter comes first. Which is also why I favor multiple functions instead of extra parameters. I would much prefer to be able to do this:
To me, that is much simpler and easier to remember and understand. I’m not a math major, and it is super clear. In my mind, it is hands down much, much better than this:
Then, if I want to use a different precision, that is the only time I need a second parameter. And if it is a number, use the same unit as the first parameter. So, —— I don’t really follow what |
Indeed! This needs to be pointed out explicitly sometimes, because itʼs all too easy to just strive for compatibility with JS (or some other language not tailored to styling) in the web ecosystem. |
It's actually not, and for some very important reasons. First and most importantly, the precision you want to round to is virtually never "1 of the unit I'm using". Obviously there's no need to write Second, if there are multiple values, relying on the first one is a footgun. A seemingly-harmless change, like switching from Third, tracking the types means being aware of exact parsed syntax in a way that no other math function (or anything else in CSS, for that matter) is. In every single other instance, And even if we did do so, it would just introduce further confusion - %s are processed late, and are explicitly about their resolved value elsewhere in math functions. ( The best we could reasonably do for a default precision is to base it on the canonical unit for a given type - round to the nearest px for all lengths, etc. But that's even further removed from any hope of matching the author's intent, per my first point. Syntax sugar is great when it simplifies a common case, and improves overall readability by removing obvious details. It's bad when it causes more special cases you have to worry about.
As your examples show, it's literally just a matter of placing the keyword before or after the We went for the keyword for two reasons: first, as dbaron stated (hopefully captured in the minutes?), there are actually more rounding modes than this, particularly "round to nearest, but resolves ties by X" (instead of always resolving a tie as "up"), and keywords are compatible with adding such control later; second, just in case this is something that an author or library wants to make controllable, a keyword can be controlled via a variable, but part of a function name can't be. (In JS it can, but we don't offer that sort of concatenation and indirection in CSS.)
Some variety of modulus operator is common to virtually every programming language in existence. If you don't know when you'll use mod, that's fine, you don't need it then. But, as the existence of the terrible abuse-the-precision-range-of-doubles hack linked on Twitter shows, people do want mod functionality. |
Hi, Found this thread while searching for solutions to a problem that seems fairly similar to comment 3. Awesome to see these new functions will eventually make it into my browser. Firstly, was curious what very rough timeline I'd be looking at in terms of going "oh, <browser> can do that now" :)? IOW, if I were to add a "revisit this" date to my mental calendar, would that be in say 2024, or halfway through 2023, or maybe even late 2022...? Etc. (I appreciate the general separation between spec and implementation (where dates become more concrete), hence the "rough". Perhaps there is related precedent in other similar areas to draw upon.) Also, after considering the functionality being added, I wondered if these new features may not actually solve for my use-case as specified. Sometimes my slightly handwavy mental models of certain aspects of CSS leads me down dead ends, but I wonder if the way I interpreted things here may actually be interesting. I happen to currently have a As currently specified. I find myself hitting the walls of the percentage sizing model semi-frequently, and perhaps I've done that here (I should probably go read it...). I mention this use case in case I haven't gone completely off the deep end (in terms of "there's no semantically sensible spot in the usage model to slot this into"), because if it were reasonable to do this sort of thing (maybe where the percentage has a known size to work with in a parent somewhere?) it would make it possible to have my cake and eat it too: I'd be able to a) have the box model natively size my elements while b) locking my canvas' to a non-fractional width and thus eliminate antialiasing and blur. Now, off to implement some sort of hacky workaround in JS involving leaving a dedicated width for the legend... |
It's been in the specs for quite a while; when it shows up in browsers is entirely up to browsers and we have no control over this (and in many cases, browsers don't know or choose not to announce timing information until something is actually ready to ship). That said, I believe Safari and Chrome are actively implementing at the moment. Not sure about Firefox.
|
Thanks for replying and the info! Announcing at implementation time makes a lot of sense, that would likely reduce overall noise. I'll be sure to keep an eye on Chrome, this is very neat. Very cool to hear that this *will* actually support percentile values. That should make canvas alignment use cases a tad easier ❤️ (And I later realized I could just |
Worth reading - CSS math: https://css-tricks.com/using-absolute-value-sign-rounding-and-modulo-in-css-today |
Graphic designers often specify a rectangular grid using a fixed module, i.e. a relative or absolute length that other measures are an integer multiple or subdivision of. In stylesheets, often several length units are used for different purposes, e.g. font size in
pt
, line height inem
, border width inpx
, margins inmm
, widths in%
, heights invh
and so on. To make them match up nicely and to assure the same results across different implementations, authors would need some method to influence or even control rounding behavior. Instead of classicround(value, precision)
,floor(value)
andceil(value)
functions found in many programming languages and spreadsheet applications for floating point numbers, I believe CSS users would best be served by a round to nearest multiple function, for values usually come with a unit. For the reasons given in #905 I would call itmod()
.The text was updated successfully, but these errors were encountered: